Hmbown/CodeWhale · error · Error
invalid draft id
Error message
invalid draft id
What it means
draftKey() builds KV keys of the form draft:<type>:<id> and refuses ids that fail /^[A-Za-z0-9._-]{1,128}$/ - empty, longer than 128 chars, or containing characters (colons, spaces, slashes, unicode, base64 '+'/'=') that would corrupt the key format or break parseDraftKey() round-tripping.
Source
Thrown at web/lib/community-agent.ts:65
export interface UsageLog {
date: string;
calls: number;
inputTokens: number;
outputTokens: number;
}
export interface DeepSeekEnv {
baseUrl?: string;
model?: string;
}
const AGENT_DRAFT_TYPE_SET = new Set<string>(AGENT_DRAFT_TYPES);
const DRAFT_ID_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;
export function draftKey(type: AgentDraftType, id: string): string {
if (!DRAFT_ID_PATTERN.test(id)) {
throw new Error("invalid draft id");
}
return `draft:${type}:${id}`;
}
export function parseDraftKey(key: string): { type: AgentDraftType; id: string } | null {
const match = /^draft:([^:]+):([^:]+)$/.exec(key);
if (!match || !AGENT_DRAFT_TYPE_SET.has(match[1]) || !DRAFT_ID_PATTERN.test(match[2])) {
return null;
}
return { type: match[1] as AgentDraftType, id: match[2] };
}
export function isAgentDraft(value: unknown): value is AgentDraft {
if (!value || typeof value !== "object") return false;
const draft = value as Record<string, unknown>;
return (
typeof draft.id === "string" &&
DRAFT_ID_PATTERN.test(draft.id) &&View on GitHub (pinned to 8880682c63)
Solutions
- Generate ids from a safe alphabet, e.g. crypto.randomUUID() (hyphens are allowed)
- Slugify free text before use: lowercase, replace [^a-z0-9._-]+ with '-', slice to 128
- Validate with the same regex in the UI and reject early with a friendly message
Example fix
// before
const key = draftKey('dispatch', rawTitle);
// after
const id = rawTitle.toLowerCase().replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 128);
if (!id) throw new Error('draft id collapsed to empty after slugify');
const key = draftKey('dispatch', id); Defensive patterns
Strategy: type-guard
Validate before calling
const DRAFT_ID = /^[A-Za-z0-9._-]{1,128}$/;
if (!DRAFT_ID.test(id)) {
id = id.toLowerCase().replace(/[^a-z0-9._-]+/g, '-').slice(0, 128) || crypto.randomUUID();
} Type guard
const DRAFT_ID_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;
function isDraftId(id) {
return typeof id === 'string' && DRAFT_ID_PATTERN.test(id);
}
// usage: if (!isDraftId(id)) return badRequest('invalid draft id'); Prevention
- Generate ids with crypto.randomUUID() or slugs, never free text
- Reject invalid ids at the API boundary with a 400 before they reach draftKey()
- Keep the id pattern in one shared constant so client and server validate identically
When it happens
Trigger: Passing user-supplied titles, URLs, or free text as the draft id; ids containing ':' which would shift key segments; an id that is empty after trimming.
Common situations: Using the chat subject or issue title directly as the id; base64-encoded ids; copy-paste ids with a trailing newline.
Related errors
- invalid draft key
- ${name} is unavailable in Workflow scripts: runs must be det
- new Date()/Date() is unavailable in Workflow scripts: runs m
- task(): expected an options object
- ${envelope.error}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/06fe1d94a066e94c.
Report an issue: GitHub.