chroma-core/chroma · error · Error
The task type cannot be changed after initialization.
Error message
The task type cannot be changed after initialization.
What it means
Intended to block changing the Gemini taskType (RETRIEVAL_DOCUMENT vs RETREVAL_QUERY etc.) after initialization, for the same reason as the model lock: task type shapes the vectors. Caveat grounded in the source: it compares oldConfig.taskType/newConfig.taskType (camelCase) while getConfig() emits task_type (snake_case), so for configs round-tripped through getConfig() both sides are undefined and this error can never fire; it only triggers when callers supply records carrying a literal camelCase taskType key.
Source
Thrown at clients/js/packages/chromadb-core/src/embeddings/GoogleGeminiEmbeddingFunction.ts:125
getConfig(): StoredConfig {
return {
api_key_env_var: this.api_key_env_var,
model_name: this.model,
task_type: this.taskType,
};
}
validateConfigUpdate(
oldConfig: Record<string, any>,
newConfig: Record<string, any>,
): void {
if (oldConfig.model_name !== newConfig.model_name) {
throw new Error("The model name cannot be changed after initialization.");
}
if (oldConfig.taskType !== newConfig.taskType) {
throw new Error("The task type cannot be changed after initialization.");
}
}
validateConfig(config: Record<string, any>): void {
validateConfigSchema(config, "google_generative_ai");
}
}
View on GitHub (pinned to aecdd12c8a)
Solutions
- Keep the task type identical across updates — fetch the stored config and reuse the field
- Create a new collection if the task type genuinely must change
- Library-level fix: compare oldConfig.task_type !== newConfig.task_type so the guard matches the keys getConfig() actually emits
Example fix
// before (library code): key never matches getConfig() output
if (oldConfig.taskType !== newConfig.taskType) {
throw new Error("The task type cannot be changed after initialization.");
}
// after: compare the key the config actually stores
if (oldConfig.task_type !== newConfig.task_type) {
throw new Error("The task type cannot be changed after initialization.");
} Defensive patterns
Strategy: validation
Validate before calling
function taskTypeOf(cfg: Record<string, any>): unknown {
return cfg.taskType ?? cfg.task_type; // cover both spellings: the guard reads camelCase, getConfig() emits snake_case
}
function assertSameTaskType(oldCfg: Record<string, any>, newCfg: Record<string, any>): void {
if (taskTypeOf(oldCfg) !== taskTypeOf(newCfg)) {
throw new Error("task type is immutable; create a new collection instead");
}
} Try / catch
try {
await applyConfigUpdate(collection, newCfg);
} catch (e) {
if (e instanceof Error && /task type cannot be changed/i.test(e.message)) {
// task type differs: create a new collection; retrying will not help
}
throw e;
} Prevention
- Normalize config keys to snake_case before comparing or updating — the library's own guard checks mismatched key spellings
- Treat task type like the model: fixed per collection, changed only via new collection
- Report the taskType/task_type key mismatch upstream so the guard actually fires
When it happens
Trigger: validateConfigUpdate() invoked with old/new records that both contain a camelCase taskType key with different values — e.g. a wrapper that camelCases config keys before calling update, or hand-built config objects.
Common situations: Wrapper layers normalizing snake_case API config into camelCase; example code constructing config objects manually; otherwise usually seen as a silent no-op with getConfig()-produced configs, which is itself a bug worth reporting.
Related errors
- The model name cannot be changed after initialization.
- Changing the URL is not allowed.
- Cannot change model name.
- Config is missing a required field
- Google API key is required. Please provide it in the constru
AI-assisted analysis of chroma-core/chroma@aecdd12c8a (2026-08-16).
Data as JSON: /api/errors/385f3125a5458847.
Report an issue: GitHub.