{"record":{"id":"61403b4ac098baec","repo":"can1357/oh-my-pi","slug":"cachedcontent-must-not-be-blank","errorCode":null,"errorMessage":"cachedContent must not be blank","messagePattern":"cachedContent must not be blank","errorType":"validation","errorClass":"AIError.ValidationError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/google-shared.ts","lineNumber":883,"sourceCode":"\t\t\tcfg.thinkingLevel = thinking.level as ThinkingLevel;\n\t\t} else if (thinking.budgetTokens !== undefined) {\n\t\t\tcfg.thinkingBudget = thinking.budgetTokens;\n\t\t}\n\t\tconfig.thinkingConfig = cfg;\n\t}\n\n\tif (options.signal) {\n\t\tif (options.signal.aborted) {\n\t\t\tthrow new AIError.AbortError(\"Request aborted\");\n\t\t}\n\t\tconfig.abortSignal = options.signal;\n\t}\n\n\tif (options.cachedContent !== undefined) {\n\t\t// Blank names are never valid resource references; anything else stays\n\t\t// opaque so we do not invent format/model/project checks here.\n\t\tif (options.cachedContent.trim().length === 0) {\n\t\t\tthrow new AIError.ValidationError(\"cachedContent must not be blank\");\n\t\t}\n\t\tconst incompatibleFields = [\n\t\t\tconfig.systemInstruction !== undefined && \"systemInstruction\",\n\t\t\tconfig.tools !== undefined && \"tools\",\n\t\t\tconfig.toolConfig !== undefined && \"toolConfig\",\n\t\t].filter((field): field is string => Boolean(field));\n\t\tif (incompatibleFields.length > 0) {\n\t\t\tthrow new AIError.ValidationError(\n\t\t\t\t`cachedContent cannot be combined with request-level ${incompatibleFields.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t\tconfig.cachedContent = options.cachedContent;\n\t}\n\n\treturn {\n\t\tmodel: model.id,\n\t\tcontents,\n\t\tconfig,","sourceCodeStart":865,"sourceCodeEnd":901,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/google-shared.ts#L865-L901","documentation":"buildGoogleGenerateContentParams validates options.cachedContent and throws AIError.ValidationError when it is whitespace-only. cachedContent must be a valid Google resource name referencing a cached context; a blank string can never be valid, so the library fails fast client-side.","triggerScenarios":"Passing cachedContent: \"\" or \"   \" (e.g. from an empty config field or env var that defaults to empty string) into the Google request options.","commonSituations":"Config/env var like GOOGLE_CACHED_CONTENT unset but read as empty string instead of undefined; UI form field left blank; template default interpolated as empty.","solutions":["Only pass cachedContent when a non-empty value exists: omit the field instead of sending \"\"","Fix the config source so unset values become undefined, not \"\"","Trim and validate the cached context name before constructing options"],"exampleFix":"// before\nconst params = { cachedContent: process.env.GOOGLE_CACHED_CONTENT ?? \"\" };\nawait streamGoogle(model, params);\n// after\nconst cachedContent = process.env.GOOGLE_CACHED_CONTENT?.trim() || undefined;\nawait streamGoogle(model, { ...baseParams, cachedContent });","handlingStrategy":"validation","validationCode":"function requireCachedContent(name: string | undefined): string | undefined {\n  if (name === undefined) return undefined;\n  const trimmed = name.trim();\n  if (!trimmed) throw new TypeError(\"cachedContent configured but blank — unset it or provide a valid resource name\");\n  return trimmed;\n}","typeGuard":"function isNonBlank(v: unknown): v is string {\n  return typeof v === \"string\" && v.trim().length > 0;\n}","tryCatchPattern":"try {\n  await streamGoogle(model, { ...params, cachedContent });\n} catch (err) {\n  if (err instanceof AIError.ValidationError && err.message.includes(\"cachedContent\")) {\n    logger.warn(\"dropping blank cachedContent\");\n    return await streamGoogle(model, params); // retry without caching\n  }\n  throw err;\n}","preventionTips":["Coalesce empty env vars / config strings to undefined before building request options","Validate config at startup: a configured-but-blank cache name should fail fast in CI, not at request time","Trim and sanity-check resource names (projects/.../cachedContents/...) when loading from config","Omit optional fields entirely instead of passing empty strings"],"tags":["google","validation","cached-content","configuration"],"backgroundTag":"blank-required-field","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}