mastra-ai/mastra · error
Invalid model string format: "${config}". Expected format: "
Error message
Invalid model string format: "${config}". Expected format: "mastra/provider/model" What it means
The embedding model router parses model strings into provider/model (or gateway/provider/model) identifiers. When the string starts with the Mastra gateway id ('mastra'), it requires at least 3 slash-separated segments; otherwise it throws 'Invalid model string format: "<config>". Expected format: "mastra/provider/model"'. This guard exists because gateway model IDs may themselves contain slashes, so the remainder is re-joined with parts.slice(1).
Source
Thrown at packages/core/src/llm/model/embedding-router.ts:140
// spec). This wrapper keeps exposing the V2 interface; doEmbed adapts.
private providerModel: EmbeddingModelV3;
constructor(config: string | OpenAICompatibleConfig) {
// Normalize config to always have provider and model IDs
let normalizedConfig: {
providerId: string;
modelId: string;
url?: string;
apiKey?: string;
headers?: Record<string, string>;
};
if (typeof config === 'string') {
// Parse provider/model or gateway/provider/model from string.
const parts = config.split('/');
if (parts[0] === MASTRA_GATEWAY_ID) {
if (parts.length < 3) {
throw new Error(`Invalid model string format: "${config}". Expected format: "mastra/provider/model"`);
}
normalizedConfig = { providerId: MASTRA_GATEWAY_ID, modelId: parts.slice(1).join('/') };
} else {
if (parts.length !== 2) {
throw new Error(`Invalid model string format: "${config}". Expected format: "provider/model"`);
}
const [providerId, modelId] = parts as [string, string];
normalizedConfig = { providerId, modelId };
}
} else if ('providerId' in config && 'modelId' in config) {
normalizedConfig = {
providerId: config.providerId,
modelId: config.modelId,
url: config.url,
apiKey: config.apiKey,
headers: config.headers,
};
} else {View on GitHub (pinned to 75dd419e61)
Solutions
- Use the full three-segment format: 'mastra/<provider>/<model>', e.g. 'mastra/openai/text-embedding-3-small'
- If not using the Mastra gateway, drop the 'mastra/' prefix and pass '<provider>/<model>' instead
- Log/print the config value being passed to catch dynamic string-building bugs
- Validate the model string with a regex before constructing the router
Example fix
// before
new EmbeddingRouter('mastra/openai'); // throws
// after
new EmbeddingRouter('mastra/openai/text-embedding-3-small'); Defensive patterns
Strategy: validation
Validate before calling
function assertModelString(config) {
const parts = config.split('/');
if (parts[0] === 'mastra') {
if (parts.length < 3) throw new Error(`Invalid model string: "${config}". Expected "mastra/provider/model"`);
} else if (parts.length !== 2) {
throw new Error(`Invalid model string: "${config}". Expected "provider/model"`);
}
}
assertModelString(modelConfig); // call before constructing the router Type guard
function isValidModelString(config) {
if (typeof config !== 'string') return false;
const parts = config.split('/');
return parts[0] === 'mastra' ? parts.length >= 3 : parts.length === 2;
} Try / catch
try {
const router = new EmbeddingRouter(config);
} catch (e) {
if (e.message.startsWith('Invalid model string format')) {
console.error(`Bad MODEL env/config: ${config}. Use "provider/model" or "mastra/provider/model".`);
process.exit(1);
} else {
throw e;
}
} Prevention
- Always include both provider and model segments for gateway strings: 'mastra/<provider>/<model>'
- Validate model strings with a regex before constructing the router
- Log the resolved model config at startup to catch truncation in dynamic builders
- Keep gateway and direct provider formats separate in config files to avoid mixed forms
When it happens
Trigger: Constructing an embedding model/router with a string like 'mastra/openai' (only 2 segments) or 'mastra' alone, i.e. any 'mastra/...' string without a provider AND model segment after the gateway id.
Common situations: Migrating from 'provider/model' strings to gateway format and dropping a segment; assuming 'mastra/provider' is enough; dynamically building the model string and truncating the model id; typos like 'mastra/openai/text-embedding-3/' — those parse, but 'mastra/openai' does not.
Related errors
- Vector configuration is required to embed text.
- For custom model, modelAbsoluteDirPath is required in FlagEm
- For custom model, modelName is required in FlagEmbedding.ini
- Tried to upsert embeddings but this Memory instance doesn't
- AcpAgent does not support resuming suspended generate calls
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/5456d50f7e0b7b95.
Report an issue: GitHub.