paperclipai/paperclip · error
${label} must be between 1 and ${maximum} characters
Error message
${label} must be between 1 and ${maximum} characters What it means
assertBoundedIdentifier validates that a Chat SDK state identifier (label naming the field) is a non-empty string no longer than the given maximum. storageKey and constructors call it for keys, endpoint ids, and similar names. Empty or oversized identifiers would break namespacing or persistence bounds, so the adapter rejects them eagerly.
Source
Thrown at server/src/services/chat-sdk-state.ts:74
interface StateEnvelope {
kind: StateKind;
schemaVersion: typeof STATE_SCHEMA_VERSION;
value: unknown;
}
export interface PaperclipChatSdkStateOptions extends ChatSdkStateScope {
maxValueBytes?: number;
now?: () => Date;
persistence: ChatSdkStatePersistence;
}
function assertBoundedIdentifier(
label: string,
value: string,
maximum: number,
): void {
if (!value || value.length > maximum) {
throw new Error(`${label} must be between 1 and ${maximum} characters`);
}
}
function assertTtl(label: string, ttlMs: number): void {
if (!(Number.isFinite(ttlMs) && ttlMs > 0)) {
throw new Error(`${label} must be a positive finite number`);
}
}
function storageKey(kind: StateKind, logicalKey: string): string {
assertBoundedIdentifier(
"Chat SDK state key",
logicalKey,
MAX_LOGICAL_KEY_LENGTH,
);
const digest = createHash("sha256").update(logicalKey).digest("hex");
return `${kind}:${digest}`;
}View on GitHub (pinned to 01ad858492)
Solutions
- Trim and validate the identifier length before calling the API
- Truncate or hash long identifiers before using them as state keys
- Check upstream data sources for empty values and default or reject early
Example fix
// before
await state.set(userId, value);
// after
if (!userId || userId.length > 128) throw new Error(`bad userId: ${userId?.length}`);
await state.set(userId, value); Defensive patterns
Strategy: validation
Validate before calling
function validId(v: unknown, max: number): v is string { return typeof v === 'string' && v.length >= 1 && v.length <= max; } Type guard
function isBoundedString(v: unknown, max = 256): v is string { return typeof v === 'string' && v.length > 0 && v.length <= max; } Try / catch
try { await state.set(key, value); } catch (err) { if (/must be between 1 and .* characters/.test((err as Error).message)) { /* fix key, retry */ } else throw err; } Prevention
- Validate identifiers at system boundaries (webhooks, APIs) before use
- Hash or truncate long composite keys
- Never allow empty-string defaults for id fields
When it happens
Trigger: Passing an empty string (''), undefined-as-string, or an identifier exceeding the configured maximum (e.g. a very long threadId, agentId, or state key) into a Chat SDK state API, constructor, or storageKey().
Common situations: Building state keys by concatenating user/session ids without length limits; storing full URLs or JSON blobs as keys; config where a tenant/org id is missing and defaults to ''.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- device-login promotion: the account identifier cannot form a
- Unsafe ${label}: ${result}
- Invalid normalized OpenCode session id
- Invalid Discord command owner identifier
- Invalid Discord form token
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/0e0a34ed5e3355db.
Report an issue: GitHub.