can1357/oh-my-pi · error · AIError.ValidationError
cachedContent cannot be combined with request-level
Error message
cachedContent cannot be combined with request-level ${incompatibleFields.join(", ")} What it means
Google's context caching API does not allow request-level systemInstruction, tools, or toolConfig alongside cachedContent (the cache already carries them). buildGoogleGenerateContentParams detects any of these set together with cachedContent and throws AIError.ValidationError listing the offending fields.
Solutions
- Remove the request-level systemInstruction/tools/toolConfig and rely on what was baked into the cache
- Create the cached context with the system instruction and tools you need, then send only messages + cachedContent
- Split your code path: separate cache-backed requests from regular requests
- If tools differ per request, do not use cachedContent for those calls
Example fix
// before
await streamGoogle(model, { system, tools, messages, cachedContent: cacheName });
// after
await streamGoogle(model, { messages, cachedContent: cacheName }); // system/tools live in the cache
// or for per-request tools: create a cache per toolset, or drop cachedContent Defensive patterns
Strategy: validation
Validate before calling
function assertCacheCompatible(params: { system?: unknown; tools?: unknown; toolConfig?: unknown; cachedContent?: string }) {
if (!params.cachedContent) return;
const conflicts = [
params.system !== undefined && "systemInstruction",
params.tools !== undefined && "tools",
params.toolConfig !== undefined && "toolConfig",
].filter(Boolean);
if (conflicts.length) throw new TypeError(`cachedContent cannot be combined with ${conflicts.join(", ")}`);
} Type guard
function isCacheOnlyRequest(p: { system?: unknown; tools?: unknown; cachedContent?: string }): p is { cachedContent: string } {
return p.cachedContent !== undefined && p.system === undefined && p.tools === undefined;
} Try / catch
try {
await streamGoogle(model, params);
} catch (err) {
if (err instanceof AIError.ValidationError && err.message.startsWith("cachedContent cannot be combined")) {
const { system, tools, toolConfig, ...rest } = params;
return await streamGoogle(model, rest); // let the cache supply system/tools
}
throw err;
} Prevention
- Structure your request builder so cache-backed requests take a distinct params shape without system/tools
- Create caches that already include the systemInstruction and tools each call needs
- Encode this constraint in your types (discriminated union: CacheRequest vs StandardRequest) so TS rejects the combination
- Document in your codebase that Google cachedContent is mutually exclusive with request-level config
When it happens
Trigger: Passing cachedContent plus systemInstruction, tools, or toolConfig in the same request options — e.g. standard agent params (with tools attached) reused for a cache-backed call.
Common situations: Reusing a general request builder that always attaches tools for cached-context calls; forgetting that the cached context was created with its own system instruction/tools; Google tool-caching tutorials that warn against duplicating config.
Related errors
- cachedContent must not be blank
- `context.tools` must be an array when present
- Host tool at index must provide a non-empty name
- Host tool " " must provide a JSON Schema object
- Host tool " " must provide a non-empty description
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/90874fa0e0316518.
Report an issue: GitHub.
Appendix: source
Thrown at packages/ai/src/providers/google-shared.ts:891
if (options.signal.aborted) {
throw new AIError.AbortError("Request aborted");
}
config.abortSignal = options.signal;
}
if (options.cachedContent !== undefined) {
// Blank names are never valid resource references; anything else stays
// opaque so we do not invent format/model/project checks here.
if (options.cachedContent.trim().length === 0) {
throw new AIError.ValidationError("cachedContent must not be blank");
}
const incompatibleFields = [
config.systemInstruction !== undefined && "systemInstruction",
config.tools !== undefined && "tools",
config.toolConfig !== undefined && "toolConfig",
].filter((field): field is string => Boolean(field));
if (incompatibleFields.length > 0) {
throw new AIError.ValidationError(
`cachedContent cannot be combined with request-level ${incompatibleFields.join(", ")}`,
);
}
config.cachedContent = options.cachedContent;
}
return {
model: model.id,
contents,
config,
};
}
/**
* Drive the `streamGoogle` / `streamGoogleVertex` event flow: build the assistant message,
* push start/done/error events, run `consumeGoogleStream`, and translate thrown errors into
* the canonical `error` event shape.
*View on GitHub (pinned to 9690622007)