KeygraphHQ/shannon · error · Error
SHANNON_AI_MODEL must be "<provider>:<model-id>", got "${tri
Error message
SHANNON_AI_MODEL must be "<provider>:<model-id>", got "${trimmed}". Example: ${DEFAULT_MODEL_SPEC} What it means
parseModelSpec rejects a SHANNON_AI_MODEL spec that contains no colon. The spec must follow '<provider>:<model-id>'; the FIRST colon is the separator so colons inside a model id (notably Bedrock ARNs) survive. With no separator the provider half cannot be distinguished from the model half.
Source
Thrown at apps/worker/src/ai/models.ts:114
}
return raw;
}
export interface ModelSpec {
providerId: string;
modelId: string;
}
/**
* Parse a `<provider>:<model-id>` spec. Splits on the first colon only, so colons
* inside a model ID survive. The provider id is passed through as given — pi's
* registry validates it later — so this throws only on a malformed spec.
*/
export function parseModelSpec(spec: string): ModelSpec {
const trimmed = spec.trim();
const separator = trimmed.indexOf(':');
if (separator === -1) {
throw new Error(
`SHANNON_AI_MODEL must be "<provider>:<model-id>", got "${trimmed}". Example: ${DEFAULT_MODEL_SPEC}`,
);
}
const providerId = trimmed.slice(0, separator).trim();
const modelId = trimmed.slice(separator + 1).trim();
if (!providerId || !modelId) {
throw new Error(
`SHANNON_AI_MODEL must be "<provider>:<model-id>", got "${trimmed}". Example: ${DEFAULT_MODEL_SPEC}`,
);
}
return { providerId, modelId };
}
/** Resolve the run's model from SHANNON_AI_MODEL, falling back to the default. */
export function resolveModelSpec(): ModelSpec {View on GitHub (pinned to 1ae0a142f8)
Solutions
- Use the form '<provider>:<model-id>', e.g. 'anthropic:claude-sonnet-4-6'.
- Look up the exact provider:model id at https://pi.dev/models.
- Leave SHANNON_AI_MODEL unset to use the default 'anthropic:claude-sonnet-4-6'.
Example fix
# before export SHANNON_AI_MODEL=claude-sonnet-4-6 # after export SHANNON_AI_MODEL=anthropic:claude-sonnet-4-6
Defensive patterns
Strategy: validation
Validate before calling
const spec = process.env.SHANNON_AI_MODEL;
if (spec && !spec.includes(':')) {
console.error(`SHANNON_AI_MODEL="${spec}" must be "<provider>:<model-id>". Example: anthropic:claude-sonnet-4-6`);
process.exit(1);
} Type guard
function isModelSpec(spec: string): boolean {
const sep = spec.indexOf(':');
if (sep === -1) return false;
const provider = spec.slice(0, sep).trim();
const model = spec.slice(sep + 1).trim();
return provider.length > 0 && model.length > 0;
} Prevention
- Always write SHANNON_AI_MODEL as provider:model, copying both halves from https://pi.dev/models.
- Leave the variable unset to use the default 'anthropic:claude-sonnet-4-6' when unsure.
When it happens
Trigger: SHANNON_AI_MODEL set to a bare model id ('claude-sonnet-4-6'), a bare provider name ('anthropic'), or a slash-delimited id ('anthropic/claude-sonnet-4-6'), then parseModelSpec/resolveModelSpec runs during preflight.
Common situations: Copying only the model id from pi.dev/models and dropping the provider prefix; pasting a slash-style id from another tool; an unset $MODEL variable producing 'anthropic:' which still has a colon but see error 2.
Related errors
- SHANNON_AI_OPENAI_FORMAT must be one of: ${Object.keys(OPENA
- SHANNON_AI_OPENAI_FORMAT applies to openai models only, but
- SHANNON_AI_OPENAI_FORMAT applies to gateway runs only. Set S
- Model not found in pi registry: provider="${providerId}" mod
- Failed to load configuration schema: ${errMsg}
AI-assisted analysis of KeygraphHQ/shannon@1ae0a142f8 (2026-08-12).
Data as JSON: /api/errors/d8420451a01def12.
Report an issue: GitHub.