ruvnet/ruflo · error · Error
label may only contain [A-Za-z0-9_.\\-:/@]
Error message
label may only contain [A-Za-z0-9_.\\-:/@]
What it means
Thrown by validateLabel() (agenticow-loader.ts:91) when a branch/checkpoint label contains characters outside the whitelist regex ^[A-Za-z0-9_.\-:/@]+$. The whitelist keeps labels filesystem-safe and manifest-JSON-safe since they become keys and path components in the COW lineage manifest.
Solutions
- Replace spaces with '-' or '_' and strip punctuation: label.replace(/[^A-Za-z0-9_.\-:/@]/g, '-')
- Use slug/kebab-case labels ('exp-3-nn-branch')
- If you need arbitrary text, store it in the record's text field, not the label
Example fix
// before
await callTool('agenticow_checkpoint', { path: p, label: 'fix attempt #1 (auth)' });
// throws: label may only contain [A-Za-z0-9_.\-:/@]
// after
await callTool('agenticow_checkpoint', { path: p, label: 'fix-attempt-1-auth' }); Defensive patterns
Strategy: validation
Validate before calling
const LABEL_RE = /^[A-Za-z0-9_.\-:/@]+$/;
function sanitizeLabel(raw: string): string {
return raw.replace(/[^A-Za-z0-9_.\-:/@]/g, '-').slice(0, 256);
}
const label = sanitizeLabel(userInput);
if (!LABEL_RE.test(label)) throw new TypeError('label charset invalid'); Try / catch
try {
await callTool('agenticow_checkpoint', args);
} catch (e) {
if (e instanceof Error && e.message.startsWith('label may only contain')) {
args.label = sanitizeLabel(args.label);
return callTool('agenticow_checkpoint', args);
}
throw e;
} Prevention
- Normalize all user-supplied labels to the whitelist charset before they reach the tool
- Prefer machine-generated slug labels; treat the label as an identifier, not free text
When it happens
Trigger: A label containing spaces ('fix attempt 1'), commas, parentheses, unicode, '#', '+', or any symbol outside A-Z a-z 0-9 _ . - : / @ — submitted to agenticow_branch, agenticow_checkpoint, agenticow_rollback, agenticow_promote, or as an agenticow_speculate candidate label.
Common situations: Human-typed labels with spaces or punctuation; labels localized to non-Latin scripts; templated labels that interpolate markdown or user free text.
Related errors
- label exceeds 256 chars
- label is required
- memory path is required
- records must be a non-empty array of
- at least one candidate is required
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/5508e0ded8c16288.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/mcp-tools/agenticow-loader.ts:91
return isAbsolute(path) ? path : resolve(getProjectCwd(), path);
}
/**
* Lineage manifest companion path. agenticow persists the COW chain
* (working → checkpoints → base) into `<file>.agenticow.json` next to the
* `.rvf` data file. Without it, forks/checkpoints are in-memory only and
* disappear when the AgenticMemory handle closes.
*/
export function manifestFor(file: string): string {
return `${file}.agenticow.json`;
}
/** Validate a COW branch/checkpoint label (alnum + a small safe symbol set). */
export function validateLabel(label: string): string {
if (!label || typeof label !== 'string') throw new Error('label is required');
if (label.length > 256) throw new Error('label exceeds 256 chars');
if (!/^[A-Za-z0-9_.\-:/@]+$/.test(label)) {
throw new Error('label may only contain [A-Za-z0-9_.\\-:/@]');
}
return label;
}
/**
* Open (or create) a memory file, restoring its COW chain from the lineage
* manifest when one exists. When neither the `.rvf` nor the manifest exists,
* `dimension` is required to create a fresh base.
*/
export async function openWithLineage(api: AgenticowApi, file: string, dimension?: number) {
const manifest = manifestFor(file);
if (existsSync(manifest)) {
return (api.AgenticMemory as any).load(manifest);
}
const opts: any = {};
if (typeof dimension === 'number' && Number.isInteger(dimension) && dimension > 0) {
opts.dimension = dimension;
} else if (!existsSync(file)) {View on GitHub (pinned to fa13ee4ad6)