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

  1. Trim and validate the identifier length before calling the API
  2. Truncate or hash long identifiers before using them as state keys
  3. 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

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


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/0e0a34ed5e3355db. Report an issue: GitHub.