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
- Refresh the acceptance list (acceptance.list) and use a current id.
- Verify the caller is the acceptance owner or a member of its workspace — the model is scope-filtered.
- 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
- Always resolve acceptance ids from acceptance.list, never from cached URLs.
- Pass ids through the model scope filter (userId + workspaceId) so cross-workspace ids fail cleanly.
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.