paperclipai/paperclip · error · Error

Expected ACPX permission mode is invalid

Error message

Expected ACPX permission mode is invalid

What it means

validateExpected validates the caller-supplied expected session identity used for recovery. Unlike the persisted-record check, permissionMode is optional here; the error is thrown only when the caller provides one that is not a recognized permission mode. This catches bad values passed by the caller rather than corruption in the stored record.

Source

Thrown at packages/paperclip-runner/src/drivers/acpx/recovery-identity.ts:261

    expected.acpxRecordId,
    expected.backendSessionId,
    expected.agentSessionId,
    expected.requestedModel,
    expected.effectiveModel,
  ]) {
    validateIdentity(value, "expected ACPX");
  }
  if (
    !isDigest(expected.profileDigest) ||
    !isDigest(expected.workspaceDigest)
  ) {
    throw new Error("Expected ACPX identity digest is invalid");
  }
  if (
    expected.permissionMode !== undefined &&
    !isPermissionMode(expected.permissionMode)
  ) {
    throw new Error("Expected ACPX permission mode is invalid");
  }
  validateFenceCandidates(expected.providerLifetimeFenceCandidates);
}

function validateFenceCandidates(
  value: unknown,
): asserts value is readonly [number, number, number] {
  if (
    !Array.isArray(value) ||
    value.length !== 3 ||
    value.some(
      (port) => !Number.isSafeInteger(port) || port < 49_152 || port > 65_535,
    ) ||
    new Set(value).size !== 3
  ) {
    throw new Error("ACPX provider lifetime fence candidates are invalid");
  }
}

View on GitHub (pinned to 01ad858492)

Solutions

  1. Use one of the library's exact permission mode strings for expected.permissionMode.
  2. Omit permissionMode from the expected identity if you do not need to constrain recovery — it is optional.
  3. Validate the mode against the same isPermissionMode predicate your code uses before calling verifyExpectedAcpxIdentity.

Example fix

// before
verifyExpectedAcpxIdentity(expected, record); // expected.permissionMode = "BYPASS"
// after
verifyExpectedAcpxIdentity({ ...expected, permissionMode: "bypassAll" }, record); // exact enum value
Defensive patterns

Strategy: validation

Validate before calling

if (expected.permissionMode !== undefined && !KNOWN_PERMISSION_MODES.includes(expected.permissionMode)) {
  throw new Error(`Invalid expected permissionMode: ${expected.permissionMode}`);
}

Type guard

const isKnownMode = (v: unknown): v is PermissionMode =>
  typeof v === "string" && ["default", "acceptEdits", "bypassAll"].includes(v);

Try / catch

try {
  verifyExpectedAcpxIdentity(expected, record);
} catch (e) {
  if (e.message === "Expected ACPX permission mode is invalid") {
    return verifyExpectedAcpxIdentity({ ...expected, permissionMode: undefined }, record);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling verifyExpectedAcpxIdentity (directly or via open()/acpxProviderSessionIdentity()) with expected.permissionMode defined but not matching isPermissionMode — e.g. misspelled mode, wrong casing, or a mode from another driver's vocabulary.

Common situations: Configuring recovery in code with a mode string like "BYPASS" or "bypass" instead of the exact enum value; copying option names from a different agent adapter; dynamic config where a raw CLI string is passed through unvalidated.

Understand the failure class

Background: "invalid argument", "unknown mode", "not supported": invalid enum-like argument errors explained — this error's family across 19 libraries.

Related errors


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