Skip to content

Conversation

@mpcgrid
Copy link
Collaborator

@mpcgrid mpcgrid commented Dec 11, 2025

Add support for resetting idempotency keys both from ui and sdk

✅ Checklist

  • I have followed every step in the contributing guide
  • The PR title follows the convention.
  • I ran and tested the code works

Testing

  • Created a new run with a idempotency idempotencyKey.
  • Started a new run with the same task and got redirected to the first run.
  • Deleted the key from the UI on the run details
  • Started a new run with the same task and it created a new one
  • Did the above steps using the SDK

Changelog

  • Add new action route for resetting idempotency keys via UI
  • Add reset button in Idempotency section of run detail view
  • Added API and SDK for resetting imdepotency
  • Updated docs page for this feature

Screenshots

[Screenshots]
Screenshot 2025-12-11 at 11 56 37

- Add new action route for resetting idempotency keys via UI
- Add reset button in Idempotency section of run detail view
- Added API and SDK for resetting imdepotency
- Updated docs page for this feature
@changeset-bot
Copy link

changeset-bot bot commented Dec 11, 2025

🦋 Changeset detected

Latest commit: 82fb94a

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

This PR includes changesets to release 26 packages
Name Type
@trigger.dev/sdk Patch
@trigger.dev/core Patch
@trigger.dev/python 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
@trigger.dev/build Patch
trigger.dev Patch
@trigger.dev/redis-worker Patch
@trigger.dev/schema-to-json Patch
@internal/cache Patch
@internal/clickhouse Patch
@internal/redis Patch
@internal/replication Patch
@internal/run-engine Patch
@internal/schedule-engine Patch
@internal/testcontainers Patch
@internal/tracing Patch
@internal/zod-worker 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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Walkthrough

Adds an idempotency key reset feature across server, routes, UI, SDK, and docs. Introduces ResetIdempotencyKeyService that clears idempotency keys on matching task runs; an API v1 route to reset by idempotency key; a resource-scoped Remix action route that validates params/form, authorizes the user, looks up the run and environment, and calls the service; a UI integration that posts to the reset action and shows a success toast; a path helper for the reset route; client SDK methods and response schema for the new endpoint; Trigger SDK export for the helper; updated documentation describing reset usage; and a changeset bump.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas requiring extra attention:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts — correctness of query filters for matched task runs, atomicity/side-effects of updateMany, and error handling when no rows affected.
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts — param/body validation, auth/authorization config, and HTTP error mapping.
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx — route/form validation, DB lookups with includes, environment resolution, and detailed logging/error responses.
  • apps/webapp/app/routes/.../spans.$spanParam/route.tsx — fetcher wiring, form submission state, and toast integration to ensure UX matches API responses.
  • packages/core/src/v3/apiClient/index.ts and packages/core/src/v3/schemas/api.ts — request path, body, and response schema alignment with server behavior.
  • packages/core/src/v3/idempotencyKeys.ts and packages/trigger-sdk/src/v3/idempotencyKeys.ts — exported API shape and propagation of errors to callers.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately and concisely describes the main feature being added: support for resetting idempotency keys across the webapp.
Description check ✅ Passed The PR description covers all required sections from the template including checklist completion, comprehensive testing steps, detailed changelog, and includes a screenshot demonstrating the feature.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/tri-6733-reset-an-idempotencykey

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.

Copy link
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.

Actionable comments posted: 4

🧹 Nitpick comments (3)
packages/core/src/v3/idempotencyKeys.ts (1)

1-1: Core helper for resetIdempotencyKey looks correct

The new helper cleanly delegates to apiClientManager.clientOrThrow().resetIdempotencyKey(...) and returns the correctly typed { id: string } response. This matches how other v3 helpers wrap the API client.

If you anticipate advanced usage, you could later add an optional requestOptions?: ZodFetchOptions parameter here to pass through to the client, but it’s fine to keep it simple for now.

Also applies to: 136-145

apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1)

1-44: Avoid redundant read before update in ResetIdempotencyKeyService

The service behavior is correct, but it does a findMany just to check runs.length === 0 and then an updateMany with the same where clause. You can save a round trip by using only updateMany and checking the affected row count:

-    const runs = await this._prisma.taskRun.findMany({
-      where: {
-        idempotencyKey,
-        taskIdentifier,
-        runtimeEnvironmentId: authenticatedEnv.id,
-      },
-      select: {
-        id: true,
-      },
-    });
-
-    if (runs.length === 0) {
-      throw new ServiceValidationError(
-        `No runs found with idempotency key: ${idempotencyKey} and task: ${taskIdentifier}`,
-        404
-      );
-    }
-
-    // Update all runs to clear the idempotency key
-    await this._prisma.taskRun.updateMany({
-      where: {
-        idempotencyKey,
-        taskIdentifier,
-        runtimeEnvironmentId: authenticatedEnv.id,
-      },
-      data: {
-        idempotencyKey: null,
-        idempotencyKeyExpiresAt: null,
-      },
-    });
+    const { count } = await this._prisma.taskRun.updateMany({
+      where: {
+        idempotencyKey,
+        taskIdentifier,
+        runtimeEnvironmentId: authenticatedEnv.id,
+      },
+      data: {
+        idempotencyKey: null,
+        idempotencyKeyExpiresAt: null,
+      },
+    });
+
+    if (count === 0) {
+      throw new ServiceValidationError(
+        `No runs found with idempotency key: ${idempotencyKey} and task: ${taskIdentifier}`,
+        404
+      );
+    }

This keeps the same behavior with fewer queries.

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx (1)

105-109: Consider using plain json() instead of jsonWithSuccessMessage().

The UI component already handles success feedback by checking resetFetcher.data.success === true and displaying a custom toast. Using jsonWithSuccessMessage() sets an additional session-based message that might result in duplicate notifications if there's a global toast handler reading session messages.

-    return jsonWithSuccessMessage(
-      { success: true },
-      request,
-      "Idempotency key reset successfully"
-    );
+    return json({ success: true });

If you want to keep the session message for consistency with other actions, ensure there's no global handler that would display it alongside the custom toast.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d287078 and 0210604.

📒 Files selected for processing (10)
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts (1 hunks)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx (1 hunks)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx (7 hunks)
  • apps/webapp/app/utils/pathBuilder.ts (1 hunks)
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1 hunks)
  • docs/idempotency.mdx (1 hunks)
  • packages/core/src/v3/apiClient/index.ts (2 hunks)
  • packages/core/src/v3/idempotencyKeys.ts (2 hunks)
  • packages/core/src/v3/schemas/api.ts (1 hunks)
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{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:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • packages/core/src/v3/schemas/api.ts
  • packages/core/src/v3/idempotencyKeys.ts
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • packages/core/src/v3/apiClient/index.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

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

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

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • packages/core/src/v3/schemas/api.ts
  • packages/core/src/v3/idempotencyKeys.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • packages/core/src/v3/apiClient/index.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • packages/core/src/v3/schemas/api.ts
  • packages/core/src/v3/idempotencyKeys.ts
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • packages/core/src/v3/apiClient/index.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
apps/webapp/app/v3/services/**/*.server.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Organize services in the webapp following the pattern app/v3/services/*/*.server.ts

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
**/*.{js,ts,jsx,tsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • packages/core/src/v3/schemas/api.ts
  • packages/core/src/v3/idempotencyKeys.ts
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • packages/core/src/v3/apiClient/index.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
packages/trigger-sdk/**/*.{ts,tsx}

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

In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code

Files:

  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeys.create()` to create idempotency keys for preventing duplicate task executions
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeys.create()` to create idempotency keys for preventing duplicate task executions

Applied to files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • packages/core/src/v3/idempotencyKeys.ts
  • docs/idempotency.mdx
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • packages/core/src/v3/apiClient/index.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Export tasks with unique IDs within the project to enable proper task discovery and execution

Applied to files:

  • packages/core/src/v3/idempotencyKeys.ts
  • docs/idempotency.mdx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter

Applied to files:

  • packages/core/src/v3/idempotencyKeys.ts
  • docs/idempotency.mdx
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeyTTL` option to define a time window during which duplicate triggers return the original run

Applied to files:

  • docs/idempotency.mdx
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • docs/idempotency.mdx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions

Applied to files:

  • docs/idempotency.mdx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks

Applied to files:

  • docs/idempotency.mdx
  • packages/trigger-sdk/src/v3/idempotencyKeys.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.batchTrigger()` to trigger multiple runs of a single task with different payloads

Applied to files:

  • docs/idempotency.mdx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.trigger()` with type-only imports to trigger tasks from backend code without importing the task implementation

Applied to files:

  • docs/idempotency.mdx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `yourTask.batchTrigger()` to trigger multiple runs of a task from inside another task

Applied to files:

  • docs/idempotency.mdx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Applied to files:

  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
📚 Learning: 2025-12-08T15:19:56.801Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.801Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
🧬 Code graph analysis (5)
packages/trigger-sdk/src/v3/idempotencyKeys.ts (2)
packages/core/src/v3/idempotencyKeys.ts (2)
  • createIdempotencyKey (89-98)
  • resetIdempotencyKey (138-145)
packages/core/src/v3/apiClient/index.ts (1)
  • resetIdempotencyKey (452-467)
apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts (2)
apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1)
  • ResetIdempotencyKeyService (4-44)
packages/core/src/v3/apps/http.ts (1)
  • json (65-75)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx (5)
apps/webapp/app/services/session.server.ts (1)
  • requireUserId (25-35)
apps/webapp/app/utils/pathBuilder.ts (1)
  • v3RunParamsSchema (35-37)
packages/core/src/v3/apps/http.ts (1)
  • json (65-75)
apps/webapp/app/models/message.server.ts (2)
  • jsonWithErrorMessage (125-142)
  • jsonWithSuccessMessage (106-123)
apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1)
  • ResetIdempotencyKeyService (4-44)
packages/core/src/v3/apiClient/index.ts (2)
packages/core/src/v3/apiClient/core.ts (2)
  • ZodFetchOptions (31-39)
  • zodfetch (71-78)
packages/core/src/v3/schemas/api.ts (2)
  • ResetIdempotencyKeyResponse (721-723)
  • ResetIdempotencyKeyResponse (725-725)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx (2)
apps/webapp/app/components/primitives/Toast.tsx (1)
  • ToastUI (46-94)
apps/webapp/app/utils/pathBuilder.ts (1)
  • v3RunIdempotencyKeyResetPath (332-341)
⏰ 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). (17)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 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 (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
🔇 Additional comments (7)
packages/trigger-sdk/src/v3/idempotencyKeys.ts (1)

1-6: SDK surface correctly exposes core resetIdempotencyKey

The idempotencyKeys map now forwards reset directly to the core implementation, which is exactly what you want for SDK ergonomics. No issues here.

apps/webapp/app/utils/pathBuilder.ts (1)

332-341: Reset path helper is consistent with existing routing

v3RunIdempotencyKeyResetPath composes the resource URL using the same helpers and conventions as other v3 paths; the shape matches the new resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset route. Looks good.

packages/core/src/v3/schemas/api.ts (1)

721-725: ResetIdempotencyKeyResponse schema is consistent and sufficient

The new ResetIdempotencyKeyResponse schema and inferred type mirror the other simple { id: string } responses and align with what the service returns. No changes needed.

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx (2)

301-322: LGTM on the toast handling logic.

The fetcher pattern and useEffect dependency array are correct. The success check properly waits for idle state before showing the toast.


573-603: LGTM on the reset UI implementation.

The form correctly posts to the reset path with the task identifier, and the button properly reflects the submitting state. The layout adjustments appropriately accommodate the new reset functionality.

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx (2)

13-15: LGTM on schema definition.

Using zod for validation aligns with coding guidelines for packages/core and apps/webapp.


32-56: LGTM on authorization check.

The query correctly validates that the user is a member of the organization owning this run, providing proper access control.

@ericallam
Copy link
Member

@mpcgrid can you go through the CodeRabbit review and address their comments?

@ericallam
Copy link
Member

This PR also needs a changeset, run the following command at the root of the repo:

pnpm run changeset:add

Select the @trigger.dev/sdk package and make a "patch" changeset and then push it to this PR.

Copy link
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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1)

4-30: Consider adding audit logging for idempotency key resets.

For security and debugging purposes, it would be helpful to log when idempotency keys are reset, including who performed the action and how many runs were affected.

   ): Promise<{ id: string }> {
     const { count } = await this._prisma.taskRun.updateMany({
       where: {
         idempotencyKey,
         taskIdentifier,
         runtimeEnvironmentId: authenticatedEnv.id,
       },
       data: {
         idempotencyKey: null,
         idempotencyKeyExpiresAt: null,
       },
     });

     if (count === 0) {
       throw new ServiceValidationError(
         `No runs found with idempotency key: ${idempotencyKey} and task: ${taskIdentifier}`,
         404
       );
     }

+    // Log the reset operation for audit trail
+    console.log(`Reset idempotency key: ${idempotencyKey} for task: ${taskIdentifier} in env: ${authenticatedEnv.id}, affected ${count} run(s)`);
+
     return { id: idempotencyKey };
   }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0210604 and f232367.

📒 Files selected for processing (8)
  • .changeset/quick-plums-tan.md (1 hunks)
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts (1 hunks)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx (1 hunks)
  • apps/webapp/app/utils/pathBuilder.ts (1 hunks)
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1 hunks)
  • packages/core/src/v3/apiClient/index.ts (2 hunks)
  • packages/core/src/v3/idempotencyKeys.ts (2 hunks)
  • packages/core/src/v3/schemas/api.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .changeset/quick-plums-tan.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/core/src/v3/idempotencyKeys.ts
  • apps/webapp/app/utils/pathBuilder.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.idempotencyKey.reset.tsx
  • packages/core/src/v3/schemas/api.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • packages/core/src/v3/apiClient/index.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:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • packages/core/src/v3/apiClient/index.ts
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • packages/core/src/v3/apiClient/index.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
apps/webapp/app/v3/services/**/*.server.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Organize services in the webapp following the pattern app/v3/services/*/*.server.ts

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
**/*.{js,ts,jsx,tsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • packages/core/src/v3/apiClient/index.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeys.create()` to create idempotency keys for preventing duplicate task executions
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeys.create()` to create idempotency keys for preventing duplicate task executions

Applied to files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
  • packages/core/src/v3/apiClient/index.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter

Applied to files:

  • apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Applied to files:

  • packages/core/src/v3/apiClient/index.ts
🧬 Code graph analysis (2)
apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts (2)
apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1)
  • ResetIdempotencyKeyService (4-31)
packages/core/src/v3/apps/http.ts (1)
  • json (65-75)
packages/core/src/v3/apiClient/index.ts (2)
packages/core/src/v3/apiClient/core.ts (2)
  • ZodFetchOptions (31-39)
  • zodfetch (71-78)
packages/core/src/v3/schemas/api.ts (2)
  • ResetIdempotencyKeyResponse (798-800)
  • ResetIdempotencyKeyResponse (802-802)
⏰ 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). (17)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 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 (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: typecheck / typecheck
🔇 Additional comments (3)
packages/core/src/v3/apiClient/index.ts (1)

665-680: LGTM! Well-implemented API client method.

The implementation follows established patterns in the ApiClient class, properly encodes the idempotency key parameter, and correctly uses the ResetIdempotencyKeyResponse schema for type safety.

apps/webapp/app/routes/api.v1.idempotencyKeys.$key.reset.ts (2)

31-48: LGTM! Error handling correctly implemented.

The error handling properly distinguishes between ServiceValidationError (client errors) and unexpected errors (server errors), avoiding the previous issue of treating all errors as 404s. The structured logging for unexpected errors aids debugging without leaking sensitive details to clients.


16-27: This route configuration is intentionally designed for SDK access. The corsStrategy: "all" is consistent with other SDK-accessible endpoints, and the empty authorization resource is correct for an environment-scoped operation (the actual scope is validated via authentication.environment and superScopes). No security concerns identified.

Copy link
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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1)

11-21: Critical: Add status validation to prevent race conditions (previously flagged).

This issue was raised in a previous review and remains unaddressed. The updateMany operation clears idempotency keys without validating run status, allowing keys to be cleared on active runs (EXECUTING, PENDING, RETRYING_AFTER_FAILURE, etc.). This creates a race condition where the same task can be triggered again with the same idempotency key while the original run is still active, completely breaking the idempotency guarantee.

The fix suggested in the previous review is correct: restrict resets to terminal states only.

🔎 Suggested fix (from previous review)
 const { count } = await this._prisma.taskRun.updateMany({
   where: {
     idempotencyKey,
     taskIdentifier,
     runtimeEnvironmentId: authenticatedEnv.id,
+    status: {
+      in: ["COMPLETED_SUCCESSFULLY", "COMPLETED_WITH_ERRORS", "SYSTEM_FAILURE", "INTERRUPTED", "CANCELED", "CRASHED", "EXPIRED", "TIMED_OUT"],
+    },
   },
   data: {
     idempotencyKey: null,
     idempotencyKeyExpiresAt: null,
   },
 });
🧹 Nitpick comments (1)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx (1)

588-602: Consider adding status-aware UI for better user experience.

The reset button is enabled for any run with an idempotency key, regardless of the run's status. While the service layer should enforce that only terminal runs can have their keys reset, the UI could provide better UX by disabling the button for active runs and explaining why.

This would prevent unnecessary server requests and provide clearer feedback to users.

💡 Optional enhancement
+const isTerminalStatus = [
+  "COMPLETED_SUCCESSFULLY",
+  "COMPLETED_WITH_ERRORS", 
+  "SYSTEM_FAILURE",
+  "INTERRUPTED",
+  "CANCELED",
+  "CRASHED",
+  "EXPIRED",
+  "TIMED_OUT"
+].includes(run.status);
+
 {run.idempotencyKey && (
+  <SimpleTooltip
+    button={
       <resetFetcher.Form
         method="post"
         action={v3RunIdempotencyKeyResetPath(organization, project, environment, { friendlyId: runParam })}
       >
         <input type="hidden" name="taskIdentifier" value={run.taskIdentifier} />
         <Button
           type="submit"
           variant="minimal/small"
           LeadingIcon={ArrowPathIcon}
-          disabled={resetFetcher.state === "submitting"}
+          disabled={resetFetcher.state === "submitting" || !isTerminalStatus}
         >
           {resetFetcher.state === "submitting" ? "Resetting..." : "Reset"}
         </Button>
       </resetFetcher.Form>
+    }
+    content={!isTerminalStatus ? "Can only reset idempotency keys on completed runs" : "Reset idempotency key"}
+    disableHoverableContent
+  />
 )}
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f232367 and 82fb94a.

📒 Files selected for processing (3)
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx (7 hunks)
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts (1 hunks)
  • packages/core/src/v3/schemas/api.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/v3/schemas/api.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.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:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
**/*.{js,ts,jsx,tsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
apps/webapp/app/v3/services/**/*.server.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Organize services in the webapp following the pattern app/v3/services/*/*.server.ts

Files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeys.create()` to create idempotency keys for preventing duplicate task executions
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Scope idempotency keys globally or to current run using the scope parameter

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeys.create()` to create idempotency keys for preventing duplicate task executions

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `idempotencyKeyTTL` option to define a time window during which duplicate triggers return the original run

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.

Applied to files:

  • apps/webapp/app/v3/services/resetIdempotencyKey.server.ts
⏰ 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). (23)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)

Comment on lines +304 to +322
useEffect(() => {
if (resetFetcher.data && resetFetcher.state === "idle") {
// Check if the response indicates success
if (resetFetcher.data && typeof resetFetcher.data === "object" && "success" in resetFetcher.data && resetFetcher.data.success === true) {
toast.custom(
(t) => (
<ToastUI
variant="success"
message="Idempotency key reset successfully"
t={t as string}
/>
),
{
duration: 5000,
}
);
}
}
}, [resetFetcher.data, resetFetcher.state]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Simplify success condition and add error handling.

The success check at line 307 is overly defensive and verbose. Additionally, the effect only handles success cases—there's no user feedback when the reset fails.

Consider simplifying the condition and adding error toast handling:

🔎 Suggested improvements
 useEffect(() => {
-  if (resetFetcher.data && resetFetcher.state === "idle") {
-    // Check if the response indicates success
-    if (resetFetcher.data && typeof resetFetcher.data === "object" && "success" in resetFetcher.data && resetFetcher.data.success === true) {
+  if (resetFetcher.state === "idle" && resetFetcher.data) {
+    if ("success" in resetFetcher.data && resetFetcher.data.success) {
       toast.custom(
         (t) => (
           <ToastUI
             variant="success"
             message="Idempotency key reset successfully"
             t={t as string}
           />
         ),
         { duration: 5000 }
       );
+    } else if ("error" in resetFetcher.data) {
+      toast.custom(
+        (t) => (
+          <ToastUI
+            variant="error"
+            message={resetFetcher.data.error || "Failed to reset idempotency key"}
+            t={t as string}
+          />
+        ),
+        { duration: 5000 }
+      );
     }
   }
 }, [resetFetcher.data, resetFetcher.state]);
🤖 Prompt for AI Agents
In
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx
around lines 304 to 322, simplify the overly defensive success check and add
error handling: replace the verbose "typeof" and "in" checks with a direct
optional chaining check like resetFetcher.data?.success === true when state is
"idle", and add an else branch that shows an error toast (using the same ToastUI
with variant="error") that surfaces resetFetcher.data?.message or a default
message when success is false or missing; keep the state == "idle" guard and
ensure the toast duration matches the success case.

@ericallam ericallam merged commit 7574c69 into main Dec 19, 2025
32 checks passed
@ericallam ericallam deleted the feat/tri-6733-reset-an-idempotencykey branch December 19, 2025 11:55
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.

3 participants