lobehub/lobehub · error · TRPCError

NOT_FOUND

NOT_FOUND

Error message

Acceptance not found

What it means

resolveAcceptance helper:findById returned no row for the given acceptance id. Every write procedure (accept, attachRun, saveChecklist, saveGoal, setVisibility, markRepairing, reject, rename, updateStatus, remove, addGroupFeedback, reviewChecks) routes through this resolver, so this is the canonical 'wrong id' failure across the acceptance API.

Source

Thrown at apps/server/src/routers/lambda/acceptance.ts:62

        ctx.userId,
        ctx.workspaceId ?? undefined,
      ),
    },
  });
});

// Writes: workspace mode requires at least the member role (viewers are
// read-only); personal mode passes through unrestricted.
const acceptanceWriteProcedure = acceptanceProcedure.use(requireWorkspaceRoleWhenScoped('member'));

const resolveAcceptance = async (
  ctx: { acceptanceService: AcceptanceService },
  id: string,
): Promise<AcceptanceItem> => {
  const acceptance = await ctx.acceptanceService.acceptanceModel.findById(id);

  if (!acceptance) {
    throw new TRPCError({ code: 'NOT_FOUND', message: 'Acceptance not found' });
  }

  return acceptance;
};

export const acceptanceRouter = router({
  /**
   * The user accepts the delivery — the terminal business event that closes
   * the acceptance lifecycle. The verifier's verdict is a recommendation; this
   * click is the event (a failed/uncertain round can still be accepted, which
   * means the user knowingly takes it with its exceptions).
   */
  accept: acceptanceWriteProcedure
    .input(z.object({ comment: z.string().max(2000).optional(), id: z.string() }))
    .mutation(async ({ ctx, input }) => {
      const acceptance = await resolveAcceptance(ctx, input.id);
      assertWorkspaceRowManageable(ctx, acceptance.userId, 'acceptance');

View on GitHub (pinned to 10f24d7ade)

Solutions

  1. Refresh the acceptance list (acceptance.list) and use a current id.
  2. Verify the caller is the acceptance owner or a member of its workspace — the model is scope-filtered.
  3. If migrating data, confirm the acceptance row was inserted and not rolled back.

Example fix

// before
await trpc.acceptance.accept.mutate({ id: staleId }); // NOT_FOUND

// after
const list = await trpc.acceptance.list.query();
await trpc.acceptance.accept.mutate({ id: list[0].id });
Defensive patterns

Strategy: validation

Validate before calling

const acceptance = await ctx.acceptanceService.acceptanceModel.findById(id);
if (!acceptance) throw new TRPCError({ code: 'NOT_FOUND', message: 'Acceptance not found' });

Type guard

const isAcceptanceItem = (x: unknown): x is AcceptanceItem =>
  typeof x === 'object' && x !== null && typeof (x as any).id === 'string';

Try / catch

try {
  await trpc.acceptance.accept.mutate({ id, comment });
} catch (e) {
  if (e.code === 'NOT_FOUND') refreshAcceptanceList();
}

Prevention

When it happens

Trigger: Any acceptance mutation called with an id that does not exist in the caller's scope (the model is constructed with userId + workspaceId, so the row must match the caller's ownership/scope filter). Stale id after deletion, id from a different workspace, malformed id.

Common situations: Client cached an acceptance id across a delete; URL parameter typo; cross-workspace id leak; the model's scope filter excluded it because the caller is not the owner and is in a different workspace.

Related errors


AI-assisted analysis of lobehub/lobehub@10f24d7ade (2026-08-12). Data as JSON: /api/errors/80baae32f8d05138. Report an issue: GitHub.