vercel/ai · error · Error
ACP harnessId must be a stable kebab-case identifier; receiv
Error message
ACP harnessId must be a stable kebab-case identifier; received ${JSON.stringify(settings.harnessId)}. What it means
createACPV1 validates settings.harnessId against HARNESS_ID_REGEXP, which requires a stable kebab-case identifier. The harnessId is used in logs, state files, bridge directories, and error messages, so an unstable or oddly formatted id (spaces, camelCase, symbols, empty) is rejected with a message echoing the received value.
Source
Thrown at packages/harness-acp/src/v1/acp-v1-harness.ts:158
(settings.credentialBrokering == null)
) {
throw new Error(
'ACP credentialEnv and credentialBrokering must be configured together.',
);
}
if (
settings.mcpServers != null &&
Object.prototype.hasOwnProperty.call(
settings.mcpServers,
'ai-sdk-harness-tools',
)
) {
throw new Error(
'ACP MCP server name "ai-sdk-harness-tools" is reserved for HarnessAgent tools.',
);
}
if (!HARNESS_ID_REGEXP.test(settings.harnessId)) {
throw new Error(
`ACP harnessId must be a stable kebab-case identifier; received ${JSON.stringify(settings.harnessId)}.`,
);
}
const implementation = createACPV1Implementation({ settings });
validateACPV1Implementation(implementation);
const bootstrap = createACPBootstrap({
harnessId: settings.harnessId,
implementation,
});
const permissionModeMapping = isCompletePermissionModeMapping({
value: settings.permissionModeMapping,
})
? settings.permissionModeMapping
: undefined;
return {
specificationVersion: 'harness-v1',
harnessId: settings.harnessId,View on GitHub (pinned to 69428b1f8b)
Solutions
- Convert the id to lowercase kebab-case, e.g. 'my-agent-harness'.
- Make the id stable across runs (do not include timestamps or random suffixes) so lifecycle state can be resumed.
- Check HARNESS_ID_REGEXP in acp-v1-harness.ts and match its pattern exactly.
Example fix
// before
createACP({ harnessId: 'My Coding Agent' }); // throws
// after
createACP({ harnessId: 'my-coding-agent' }); Defensive patterns
Strategy: validation
Validate before calling
const HARNESS_ID_REGEXP = /^[a-z0-9]+(-[a-z0-9]+)*$/;
function isValidHarnessId(id: string): boolean {
return HARNESS_ID_REGEXP.test(id);
}
if (!isValidHarnessId(myHarnessId)) throw new Error(`harnessId must be kebab-case: ${myHarnessId}`); Type guard
function isKebabCaseId(v: unknown): v is string {
return typeof v === 'string' && /^[a-z0-9]+(-[a-z0-9]+)*$/.test(v);
} Prevention
- Normalize names with a toKebabCase helper before assigning harnessId.
- Keep harnessId constant per logical agent — derive it from a config constant, not runtime data.
- Validate ids where they are first defined (config module) rather than at harness creation.
When it happens
Trigger: Calling createACP/createACPV1 with a harnessId such as 'My Harness', 'myHarness', 'my_harness', '', or one containing invalid characters that fail HARNESS_ID_REGEXP.
Common situations: Deriving harnessId from a display name or package name without normalizing to kebab-case; building ids dynamically per-run (defeating the 'stable' requirement for resume/state lookup); copy-paste with mixed casing.
Related errors
- maxEmbeddingsPerCall must be greater than 0
- Invalid argument for parameter output: Invalid output type.
- Model tried to call unavailable tool '${toolName}'. Availabl
- Continuation maxAgeMs must be a positive integer.
- ACP credentialEnv and credentialBrokering must be configured
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/e648f3c54334472c.
Report an issue: GitHub.