Skip to content

fix(core): use Promise.allSettled in TracingSDK flush/shutdown#3562

Closed
ericallam wants to merge 3 commits into
mainfrom
claude/issue-3556-20260512-1346
Closed

fix(core): use Promise.allSettled in TracingSDK flush/shutdown#3562
ericallam wants to merge 3 commits into
mainfrom
claude/issue-3556-20260512-1346

Conversation

@ericallam
Copy link
Copy Markdown
Member

Summary

  • Switch TracingSDK.flush() and shutdown() from Promise.all to Promise.allSettled
  • Prevents one provider's rejection from abandoning other providers' in-flight exports
  • Adds per-provider error logging for better debugging

Fixes #3556

Test plan

  • Deploy to self-hosted environment with processKeepAliveEnabled: false
  • Run task with logger.info() calls and verify they appear in trace
  • Verify no "Failed to flush tracingSDK" errors in runner logs

Switch TracingSDK.flush() and shutdown() from Promise.all to
Promise.allSettled to prevent one provider's rejection from
abandoning the other providers' in-flight exports.

This fixes an issue where user-emitted trace data (logger.info
calls, child spans) could be silently dropped on shutdown when
any provider fails to flush, particularly affecting self-hosted
deployments with processKeepAliveEnabled: false.

Fixes #3556

Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 12, 2026

🦋 Changeset detected

Latest commit: d7eae64

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 29 packages
Name Type
@trigger.dev/core Patch
@trigger.dev/build Patch
trigger.dev Patch
@trigger.dev/python Patch
@trigger.dev/redis-worker Patch
@trigger.dev/schema-to-json Patch
@trigger.dev/sdk Patch
@internal/cache Patch
@internal/clickhouse Patch
@internal/llm-model-catalog Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/schedule-engine Patch
@internal/testcontainers Patch
@internal/tracing Patch
@internal/tsql Patch
@internal/zod-worker Patch
d3-chat Patch
references-d3-openai-agents Patch
references-nextjs-realtime Patch
references-realtime-hooks-test Patch
references-realtime-streams Patch
references-telemetry Patch
@internal/sdk-compat-tests Patch
@trigger.dev/react-hooks Patch
@trigger.dev/rsc Patch
@trigger.dev/database Patch
@trigger.dev/otlp-importer Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment on lines 371 to 383
public async flush() {
await Promise.all([
const results = await Promise.allSettled([
this._traceProvider.forceFlush(),
this._logProvider.forceFlush(),
this._meterProvider.forceFlush(),
]);
const providerNames = ["trace", "log", "meter"] as const;
results.forEach((result, index) => {
if (result.status === "rejected") {
console.error(`Failed to flush ${providerNames[index]} provider:`, result.reason);
}
});
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 flush()/shutdown() no longer propagate errors to callers

With Promise.allSettled, flush() and shutdown() now always resolve (never reject), even when individual providers fail. This changes the public API contract. The callers in managed-run-worker.ts:725-738 and dev-run-worker.ts:724-737 (flushTracingSDK) wrap _tracingSDK?.flush() in Promise.race inside an outer Promise.allSettled (managed-run-worker.ts:673, dev-run-worker.ts:687), which tracks success/failure via successfulFlushes/failedFlushes. After this PR, flushTracingSDK will always resolve successfully, so "tracingSDK" will always appear in successfulFlushes even if underlying providers failed. The failure tracking at the flushAll level becomes less precise for tracing SDK failures specifically — though the individual provider errors are still logged to console by the new code. This is arguably the right tradeoff (partial success is better than total failure), but reviewers should be aware the caller-level failure detection for tracing is now effectively bypassed.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c2a49f6b-c1de-485f-8bad-30cd3b538d47

📥 Commits

Reviewing files that changed from the base of the PR and between 1e29a72 and d7eae64.

📒 Files selected for processing (1)
  • packages/core/src/v3/otel/tracingSDK.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (24)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / e2e-webapp / 🧪 E2E Tests: Webapp
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
packages/core/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (packages/core/CLAUDE.md)

Never import the root package (@trigger.dev/core). Always use subpath imports such as @trigger.dev/core/v3, @trigger.dev/core/v3/utils, @trigger.dev/core/logger, or @trigger.dev/core/schemas

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
packages/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Use pnpm run build to verify changes in public packages (packages/*)

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
{packages,integrations}/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

When modifying any public package (packages/* or integrations/*), add a changeset using pnpm run changeset:add

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
{package.json,**/*.{ts,tsx,js}}

📄 CodeRabbit inference engine (CLAUDE.md)

Pin Zod to version 3.25.76 exactly across the entire monorepo - never use a different version or version range

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js}: Import from @trigger.dev/core using subpaths only, never the root export
Always import tasks from @trigger.dev/sdk, never from @trigger.dev/sdk/v3 or deprecated client.defineJob
Add crumbs to code using // @Crumbs comments or `// `#region` `@crumbs blocks for debug tracing during development

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.{ts,tsx,js,jsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Code formatting is enforced using Prettier. Run pnpm run format before committing

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
🧠 Learnings (2)
📚 Learning: 2026-03-22T13:26:12.060Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3244
File: apps/webapp/app/components/code/TextEditor.tsx:81-86
Timestamp: 2026-03-22T13:26:12.060Z
Learning: In the triggerdotdev/trigger.dev codebase, do not flag `navigator.clipboard.writeText(...)` calls for `missing-await`/`unhandled-promise` issues. These clipboard writes are intentionally invoked without `await` and without `catch` handlers across the project; keep that behavior consistent when reviewing TypeScript/TSX files (e.g., usages like in `apps/webapp/app/components/code/TextEditor.tsx`).

Applied to files:

  • packages/core/src/v3/otel/tracingSDK.ts
📚 Learning: 2026-03-22T19:24:14.403Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3187
File: apps/webapp/app/v3/services/alerts/deliverErrorGroupAlert.server.ts:200-204
Timestamp: 2026-03-22T19:24:14.403Z
Learning: In the triggerdotdev/trigger.dev codebase, webhook URLs are not expected to contain embedded credentials/secrets (e.g., fields like `ProjectAlertWebhookProperties` should only hold credential-free webhook endpoints). During code review, if you see logging or inclusion of raw webhook URLs in error messages, do not automatically treat it as a credential-leak/secrets-in-logs issue by default—first verify the URL does not contain embedded credentials (for example, no username/password in the URL, no obvious secret/token query params or fragments). If the URL is credential-free per this project’s conventions, allow the logging.

Applied to files:

  • packages/core/src/v3/otel/tracingSDK.ts
🔇 Additional comments (1)
packages/core/src/v3/otel/tracingSDK.ts (1)

372-388: LGTM!

Also applies to: 392-408


Walkthrough

TracingSDK.flush() and TracingSDK.shutdown() now call providers' forceFlush()/shutdown() using Promise.allSettled rather than Promise.all. Rejected provider results are collected (non-Error reasons normalized to Error) and, if any fail, an AggregateError containing all provider errors is thrown. A Changeset entry was added documenting the patch release for @trigger.dev/core.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: switching from Promise.all to Promise.allSettled in TracingSDK flush/shutdown methods, which directly addresses the root cause identified in issue #3556.
Description check ✅ Passed The pull request description provides a clear summary of changes, references the linked issue (#3556), includes a test plan with specific deployment and verification steps, and follows the repository template structure.
Linked Issues check ✅ Passed The pull request fully addresses the coding requirements from issue #3556 by switching TracingSDK.flush() and shutdown() from Promise.all to Promise.allSettled, preventing provider rejections from abandoning other providers' exports, and adding error handling/logging for failed providers.
Out of Scope Changes check ✅ Passed All changes are within scope: the changeset documentation, TracingSDK implementation modifications, and error handling improvements directly target the issue #3556 objectives with no unrelated alterations.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/issue-3556-20260512-1346

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ericallam
Copy link
Copy Markdown
Member Author

@claude can you address this review:

With Promise.allSettled, flush() and shutdown() now always resolve (never reject), even when individual providers fail. This changes the public API contract. The callers in managed-run-worker.ts:725-738 and dev-run-worker.ts:724-737 (flushTracingSDK) wrap _tracingSDK?.flush() in Promise.race inside an outer Promise.allSettled (managed-run-worker.ts:673, dev-run-worker.ts:687), which tracks success/failure via successfulFlushes/failedFlushes. After this PR, flushTracingSDK will always resolve successfully, so "tracingSDK" will always appear in successfulFlushes even if underlying providers failed. The failure tracking at the flushAll level becomes less precise for tracing SDK failures specifically — though the individual provider errors are still logged to console by the new code. This is arguably the right tradeoff (partial success is better than total failure), but reviewers should be aware the caller-level failure detection for tracing is now effectively bypassed.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/core/src/v3/otel/tracingSDK.ts (1)

377-377: 💤 Low value

Consider extracting the duplicated providerNames array.

The providerNames array is duplicated in both flush() and shutdown() methods. Consider extracting it as a private static constant to follow the DRY principle.

♻️ Proposed refactor
 export class TracingSDK {
   private readonly _logProvider: LoggerProvider;
   private readonly _spanExporter: SpanExporter;
   private readonly _traceProvider: NodeTracerProvider;
   private readonly _meterProvider: MeterProvider;
+  private static readonly PROVIDER_NAMES = ["trace", "log", "meter"] as const;

   public readonly getLogger: LoggerProvider["getLogger"];
   public readonly getTracer: TracerProvider["getTracer"];

...

   public async flush() {
     const results = await Promise.allSettled([
       this._traceProvider.forceFlush(),
       this._logProvider.forceFlush(),
       this._meterProvider.forceFlush(),
     ]);
-    const providerNames = ["trace", "log", "meter"] as const;
     results.forEach((result, index) => {
       if (result.status === "rejected") {
-        console.error(`Failed to flush ${providerNames[index]} provider:`, result.reason);
+        console.error(`Failed to flush ${TracingSDK.PROVIDER_NAMES[index]} provider:`, result.reason);
       }
     });
   }

   public async shutdown() {
     const results = await Promise.allSettled([
       this._traceProvider.shutdown(),
       this._logProvider.shutdown(),
       this._meterProvider.shutdown(),
     ]);
-    const providerNames = ["trace", "log", "meter"] as const;
     results.forEach((result, index) => {
       if (result.status === "rejected") {
-        console.error(`Failed to shutdown ${providerNames[index]} provider:`, result.reason);
+        console.error(`Failed to shutdown ${TracingSDK.PROVIDER_NAMES[index]} provider:`, result.reason);
       }
     });
   }

Also applies to: 391-391

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/src/v3/otel/tracingSDK.ts` at line 377, Extract the duplicated
const array into a single private static constant and reference it from both
methods: add a private static readonly PROVIDER_NAMES = ["trace","log","meter"]
as const (inside the class in tracingSDK.ts) and replace the local providerNames
declarations in the flush() and shutdown() methods with this PROVIDER_NAMES
symbol so both methods share the same definition.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/core/src/v3/otel/tracingSDK.ts`:
- Line 377: Extract the duplicated const array into a single private static
constant and reference it from both methods: add a private static readonly
PROVIDER_NAMES = ["trace","log","meter"] as const (inside the class in
tracingSDK.ts) and replace the local providerNames declarations in the flush()
and shutdown() methods with this PROVIDER_NAMES symbol so both methods share the
same definition.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5002825e-1096-418b-8acb-1b49c3603c36

📥 Commits

Reviewing files that changed from the base of the PR and between 41a486e and c5b5fde.

📒 Files selected for processing (2)
  • .changeset/fix-tracing-sdk-flush.md
  • packages/core/src/v3/otel/tracingSDK.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
packages/core/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (packages/core/CLAUDE.md)

Never import the root package (@trigger.dev/core). Always use subpath imports such as @trigger.dev/core/v3, @trigger.dev/core/v3/utils, @trigger.dev/core/logger, or @trigger.dev/core/schemas

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
packages/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Use pnpm run build to verify changes in public packages (packages/*)

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
{packages,integrations}/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

When modifying any public package (packages/* or integrations/*), add a changeset using pnpm run changeset:add

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
{package.json,**/*.{ts,tsx,js}}

📄 CodeRabbit inference engine (CLAUDE.md)

Pin Zod to version 3.25.76 exactly across the entire monorepo - never use a different version or version range

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js}: Import from @trigger.dev/core using subpaths only, never the root export
Always import tasks from @trigger.dev/sdk, never from @trigger.dev/sdk/v3 or deprecated client.defineJob
Add crumbs to code using // @Crumbs comments or `// `#region` `@crumbs blocks for debug tracing during development

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
**/*.{ts,tsx,js,jsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Code formatting is enforced using Prettier. Run pnpm run format before committing

Files:

  • packages/core/src/v3/otel/tracingSDK.ts
🧠 Learnings (2)
📚 Learning: 2026-03-22T13:26:12.060Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 3244
File: apps/webapp/app/components/code/TextEditor.tsx:81-86
Timestamp: 2026-03-22T13:26:12.060Z
Learning: In the triggerdotdev/trigger.dev codebase, do not flag `navigator.clipboard.writeText(...)` calls for `missing-await`/`unhandled-promise` issues. These clipboard writes are intentionally invoked without `await` and without `catch` handlers across the project; keep that behavior consistent when reviewing TypeScript/TSX files (e.g., usages like in `apps/webapp/app/components/code/TextEditor.tsx`).

Applied to files:

  • packages/core/src/v3/otel/tracingSDK.ts
📚 Learning: 2026-03-22T19:24:14.403Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3187
File: apps/webapp/app/v3/services/alerts/deliverErrorGroupAlert.server.ts:200-204
Timestamp: 2026-03-22T19:24:14.403Z
Learning: In the triggerdotdev/trigger.dev codebase, webhook URLs are not expected to contain embedded credentials/secrets (e.g., fields like `ProjectAlertWebhookProperties` should only hold credential-free webhook endpoints). During code review, if you see logging or inclusion of raw webhook URLs in error messages, do not automatically treat it as a credential-leak/secrets-in-logs issue by default—first verify the URL does not contain embedded credentials (for example, no username/password in the URL, no obvious secret/token query params or fragments). If the URL is credential-free per this project’s conventions, allow the logging.

Applied to files:

  • packages/core/src/v3/otel/tracingSDK.ts
🪛 LanguageTool
.changeset/fix-tracing-sdk-flush.md

[style] ~5-~5: Consider using a different verb for a more formal wording.
Context: ...ther providers' in-flight exports. This fixes an issue where user-emitted trace data ...

(FIX_RESOLVE)

🔇 Additional comments (2)
packages/core/src/v3/otel/tracingSDK.ts (1)

371-397: LGTM!

.changeset/fix-tracing-sdk-flush.md (1)

1-5: LGTM!

@claude
Copy link
Copy Markdown

claude Bot commented May 12, 2026

Claude finished @ericallam's task in 1m 49s —— View job


Addressing Review Feedback

  • Read current tracingSDK.ts implementation
  • Read caller code in managed-run-worker.ts and dev-run-worker.ts
  • Design solution to preserve failure detection while keeping Promise.allSettled resilience
  • Implement changes
  • Commit and push

Done. Updated flush() and shutdown() to throw an AggregateError after processing all results if any providers failed. This preserves both:

  • Resilience: All providers get a chance to flush/shutdown (via Promise.allSettled)
  • Failure detection: Callers can still catch failures for successfulFlushes/failedFlushes tracking

View commit | |

…caller failure detection

Keep Promise.allSettled for resilience (all providers get a chance to flush),
but throw AggregateError if any failed so callers can still detect failures.

Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
@ericallam
Copy link
Copy Markdown
Member Author

@claude improved this pr based on this review:

Code review — PR #3562 (fix(core): use Promise.allSettled in TracingSDK flush/shutdown)

Verdict

ACCEPT-WITH-NITS — small, well-targeted fix. Rebase before merge.

Important findings

None.

Nits

  1. 🟡 Branch is behind main — diff includes an accidental revert of PR fix(core): retry TASK_PROCESS_SIGSEGV under the user's retry policy #3552 (SIGSEGV retry).
    → .changeset/retry-sigsegv.md, packages/core/src/v3/errors.ts:361,398, packages/core/test/errors.test.ts
    → Branch was cut before 8e675a4 landed on main; merging as-is would silently revert SIGSEGV retry behavior, its changeset, and its tests.
    → Rebase onto current main before merging.
  2. 🟡 Duplicate failure reporting. Each rejected provider is console.error'd inside flush()/shutdown() and then thrown as part of the AggregateError. Existing callers (e.g. managed-run-worker.ts:690-696) already
    log rejected reasons, so each failure prints twice.
    → packages/core/src/v3/otel/tracingSDK.ts:381,400
    → Drop the per-provider console.error and rely on the AggregateError carrying the cause, or accept the duplication.
  3. 🟡 AggregateError.message shadows per-provider detail. Existing caller at managed-run-worker.ts:692 logs result.reason (the AggregateError), which surfaces only the generic prefix unless .errors is inspected.
    → packages/core/src/v3/otel/tracingSDK.ts:386-388,405-407
    → Include provider names in the aggregate message (e.g. One or more providers failed to flush: ${failedNames.join(", ")}) so the existing log line stays informative.

Strengths

  • Success-path behavior is identical to before — no extra logs, no spurious throw, same return.
  • Provider-name array order correctly matches Promise.allSettled input order, so error logs identify the right exporter.
  • Failure semantics preserved via AggregateError — callers that previously detected failure via a thrown rejection still do.
  • AggregateError is safe for this package (target: es2022, engines.node >=18.20.0).
  • Changeset present, correctly scoped to @trigger.dev/core as patch.

@claude
Copy link
Copy Markdown

claude Bot commented May 12, 2026

Claude finished @ericallam's task in 1m 55s —— View job


Addressing Review Feedback

  • Rebase branch onto current main Skipping rebase (too many conflicts from diverged history). Should be done manually before merge.
  • Remove duplicate console.error logging (rely on AggregateError)
  • Improve AggregateError message to include failed provider names
  • Push changes

Done. Pushed d7eae64 with the following changes:

  1. Removed the per-provider console.error calls — the AggregateError now carries all failure information
  2. Updated AggregateError messages to include which providers failed (e.g., "One or more providers failed to flush: trace, log")

Note on rebase: The branch has significant conflicts with main (many files across workflows, webapp components, run-engine, etc.). This should be rebased manually before merging to avoid reverting PR #3552 (SIGSEGV retry).
|

…messages

- Remove per-provider console.error calls (rely on AggregateError for error propagation)
- Include failed provider names in AggregateError message for better debugging

Co-authored-by: Eric Allam <ericallam@users.noreply.github.com>
@ericallam ericallam closed this May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(v4): TracingSDK.flush() uses Promise.all, drops trace + log exports on shutdown when one provider rejects

1 participant