paperclipai/paperclip · error

List maxLength must be a positive safe integer

Error message

List maxLength must be a positive safe integer

What it means

appendToList validates the optional options.maxLength: if supplied it must be a positive safe integer, since it caps list length during the CAS append loop. Non-integers, 0, negatives, NaN, and values beyond Number.MAX_SAFE_INTEGER are rejected before any persistence work.

Source

Thrown at server/src/services/chat-sdk-state.ts:303

    }
    throw this.casExhausted("set cache value if absent");
  }

  async delete(key: string): Promise<void> {
    await this.deleteCurrent("cache", key);
  }

  async appendToList(
    key: string,
    value: unknown,
    options?: { maxLength?: number; ttlMs?: number },
  ): Promise<void> {
    this.ensureConnected();
    if (
      options?.maxLength !== undefined &&
      !(Number.isSafeInteger(options.maxLength) && options.maxLength > 0)
    ) {
      throw new Error("List maxLength must be a positive safe integer");
    }
    const storedKey = storageKey("list", key);
    const expiresAt = this.expiryFromTtl(options?.ttlMs);
    for (let attempt = 0; attempt < MAX_CAS_ATTEMPTS; attempt += 1) {
      const record = await this.persistence.read(this.scope, storedKey);
      const prior =
        record && !this.isExpired(record) ? decodeEnvelope(record, "list") : [];
      if (!Array.isArray(prior)) throw new Error("Invalid Chat SDK list state");
      const appended = [...prior, value];
      const next = options?.maxLength
        ? appended.slice(-options.maxLength)
        : appended;
      if (
        await this.compareAndSet(
          storedKey,
          record?.version ?? null,
          "list",
          next,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Validate before the call: Number.isSafeInteger(maxLength) && maxLength > 0
  2. Coerce and round config-derived values with Math.round(Number(x)) then re-check
  3. Use undefined (not 0) when no cap is desired

Example fix

// before
await state.appendToList(key, item, { maxLength: rawCap });
// after
const maxLength = rawCap === undefined ? undefined : Math.round(Number(rawCap));
if (maxLength !== undefined && !(Number.isSafeInteger(maxLength) && maxLength > 0)) {
  throw new Error(`bad maxLength: ${rawCap}`);
}
await state.appendToList(key, item, { maxLength });
Defensive patterns

Strategy: validation

Validate before calling

if (maxLength !== undefined && !(Number.isSafeInteger(maxLength) && maxLength > 0)) throw new Error('maxLength must be a positive safe integer');

Type guard

function isPositiveSafeInt(v: unknown): v is number { return typeof v === 'number' && Number.isSafeInteger(v) && v > 0; }

Try / catch

try { await state.appendToList(key, item, { maxLength }); } catch (err) { if (/maxLength must be a positive safe integer/.test((err as Error).message)) { /* correct the option and retry */ } throw err; }

Prevention

When it happens

Trigger: Passing { maxLength: 0 }, { maxLength: -10 }, { maxLength: 1.5 }, { maxLength: NaN }, or a value from unparsed/unvalidated config into appendToList(key, value, options).

Common situations: maxLength read from env/config as a string or unvalidated number; arithmetic producing fractional values (e.g. size/2); defaulting maxLength to 0 when unset.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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