lobehub/lobehub · warning · TRPCError
NOT_FOUND
NOT_FOUND
Error message
Credential not found: ${input.key} What it means
Deliberate validation throw in `creds.getByKey` (creds.ts:229). Unlike the other creds errors, this is `NOT_FOUND`, not `INTERNAL_SERVER_ERROR`, and it is thrown on purpose when no credential in `creds.list()` matches `input.key`. It is re-thrown unchanged by the catch block (which has `if (error instanceof TRPCError) throw error;`), so the client receives a clean 404 with the offending key in the message.
Source
Thrown at apps/server/src/routers/lambda/market/creds.ts:229
// Get single credential by key (optionally with decrypted values)
getByKey: credsManageProcedure
.input(
z.object({
decrypt: z.boolean().optional(),
key: z.string(),
}),
)
.query(async ({ ctx, input }) => {
log('getByKey input: %O', input);
try {
// First find the credential by key from the list
const listResult = await ctx.marketService.market.creds.list();
const cred = listResult.data?.find((c) => c.key === input.key);
if (!cred) {
throw new TRPCError({
code: 'NOT_FOUND',
message: `Credential not found: ${input.key}`,
});
}
// Then get the full credential with optional decryption
const result = await ctx.marketService.market.creds.get(cred.id, {
decrypt: input.decrypt,
});
log('getByKey success: key=%s, id=%d', input.key, cred.id);
return result;
} catch (error) {
if (error instanceof TRPCError) throw error;
log('getByKey error: %O', error);
throw new TRPCError({
cause: error,
code: 'INTERNAL_SERVER_ERROR',
message: 'Failed to get credential by key',View on GitHub (pinned to 10f24d7ade)
Solutions
- Confirm the key exists via `list` (or the UI) before calling `getByKey`.
- Treat `NOT_FOUND` on the client as 'credential missing' and prompt the user to (re)create it, not as a crash.
- Avoid hardcoding keys — store references to credential ids returned by create/list.
- If the key is environment-specific, namespace it (e.g. `prod:openai_key`) and validate against the active environment.
Example fix
// before — caller has no pre-check
const cred = await trpc.market.creds.getByKey.query({ key: 'openai_key' });
// after — verify existence via list, handle 404 gracefully
const list = await trpc.market.creds.list.query();
if (!list.data?.some((c) => c.key === 'openai_key')) {
throw new Error('OpenAI credential is not configured. Please add it in Settings.');
}
const cred = await trpc.market.creds.getByKey.query({ key: 'openai_key' }); Defensive patterns
Strategy: validation
Validate before calling
// Pre-check the key exists before calling getByKey
const list = await trpc.market.creds.list.query();
if (!list.data?.some((c) => c.key === key)) {
throw new Error(`Credential '${key}' is not configured.`);
} Type guard
function isCredKey(v: unknown): v is string { return typeof v === 'string' && v.length > 0 && v.length <= 100; } Try / catch
try {
return await trpc.market.creds.getByKey.query({ key });
} catch (e) {
const err = e as { data?: { code?: string } };
if (err.data?.code === 'NOT_FOUND') {
// prompt user to create the credential instead of crashing
throw new Error(`Credential '${key}' is missing. Please add it in Settings.`);
}
throw e;
} Prevention
- Avoid hardcoding credential keys — store ids returned by create/list.
- Pre-validate key existence with list().
- Treat NOT_FOUND as a configuration gap, not a crash.
When it happens
Trigger: Caller passes a `key` that doesn't exist in the user's credentials; key was deleted between a list call and the getByKey call; typo in the key; key belongs to a different user/workspace scope.
Common situations: Hardcoded/legacy key reference after the credential was renamed; race between delete and read; key copied from a different environment (dev vs prod).
Related errors
AI-assisted analysis of lobehub/lobehub@10f24d7ade (2026-08-12).
Data as JSON: /api/errors/8133b26e1148d7e0.
Report an issue: GitHub.