{"record":{"id":"8133b26e1148d7e0","repo":"lobehub/lobehub","slug":"not-found-8133b2","errorCode":"NOT_FOUND","errorMessage":"Credential not found: ${input.key}","messagePattern":"Credential not found: (.+?)","errorType":"error_code","errorClass":"TRPCError","httpStatus":404,"severity":"warning","filePath":"apps/server/src/routers/lambda/market/creds.ts","lineNumber":229,"sourceCode":"\n  // Get single credential by key (optionally with decrypted values)\n  getByKey: credsManageProcedure\n    .input(\n      z.object({\n        decrypt: z.boolean().optional(),\n        key: z.string(),\n      }),\n    )\n    .query(async ({ ctx, input }) => {\n      log('getByKey input: %O', input);\n\n      try {\n        // First find the credential by key from the list\n        const listResult = await ctx.marketService.market.creds.list();\n        const cred = listResult.data?.find((c) => c.key === input.key);\n\n        if (!cred) {\n          throw new TRPCError({\n            code: 'NOT_FOUND',\n            message: `Credential not found: ${input.key}`,\n          });\n        }\n\n        // Then get the full credential with optional decryption\n        const result = await ctx.marketService.market.creds.get(cred.id, {\n          decrypt: input.decrypt,\n        });\n        log('getByKey success: key=%s, id=%d', input.key, cred.id);\n        return result;\n      } catch (error) {\n        if (error instanceof TRPCError) throw error;\n        log('getByKey error: %O', error);\n        throw new TRPCError({\n          cause: error,\n          code: 'INTERNAL_SERVER_ERROR',\n          message: 'Failed to get credential by key',","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/lobehub/lobehub/blob/10f24d7ade75139093a9373b364f6bc91f3cd7db/apps/server/src/routers/lambda/market/creds.ts#L211-L247","documentation":"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.","triggerScenarios":"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.","commonSituations":"Hardcoded/legacy key reference after the credential was renamed; race between delete and read; key copied from a different environment (dev vs prod).","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."],"exampleFix":"// before — caller has no pre-check\nconst cred = await trpc.market.creds.getByKey.query({ key: 'openai_key' });\n// after — verify existence via list, handle 404 gracefully\nconst list = await trpc.market.creds.list.query();\nif (!list.data?.some((c) => c.key === 'openai_key')) {\n  throw new Error('OpenAI credential is not configured. Please add it in Settings.');\n}\nconst cred = await trpc.market.creds.getByKey.query({ key: 'openai_key' });","handlingStrategy":"validation","validationCode":"// Pre-check the key exists before calling getByKey\nconst list = await trpc.market.creds.list.query();\nif (!list.data?.some((c) => c.key === key)) {\n  throw new Error(`Credential '${key}' is not configured.`);\n}","typeGuard":"function isCredKey(v: unknown): v is string { return typeof v === 'string' && v.length > 0 && v.length <= 100; }","tryCatchPattern":"try {\n  return await trpc.market.creds.getByKey.query({ key });\n} catch (e) {\n  const err = e as { data?: { code?: string } };\n  if (err.data?.code === 'NOT_FOUND') {\n    // prompt user to create the credential instead of crashing\n    throw new Error(`Credential '${key}' is missing. Please add it in Settings.`);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["trpc","credentials","validation","not-found","read-op"],"backgroundTag":null,"analyzedSha":"10f24d7ade75139093a9373b364f6bc91f3cd7db","analyzedAt":"2026-08-12T11:43:19.543Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}