thedotmack/claude-mem · error · Error
device_id must be 1-128 characters
Error message
device_id must be 1-128 characters
What it means
Validation guard in SyncHubDO.renameDevice: the trimmed deviceId must be 1-128 characters to match the device-id constraints enforced at registration. renameDevice updates the display name in the devices table and returns whether a row matched.
Solutions
- Trim the id and check length is between 1 and 128 before calling renameDevice
- Reuse the exact device id issued at registration rather than a derived value
- Check the return value: false means no device with that id exists, not a rename failure
Example fix
// before
await stub.renameDevice(rawId, name);
// after
const id = rawId.trim();
if (id.length === 0 || id.length > 128) throw new Error('invalid device id');
await stub.renameDevice(id, name); Defensive patterns
Strategy: validation
Validate before calling
const id = rawId.trim();
if (id.length < 1 || id.length > 128) throw new Error('device id must be 1-128 chars');
const nm = normalizeDeviceName(name);
if (nm === null) throw new Error('device name must be 1-80 chars'); Type guard
const isRenamableDeviceId = (id: unknown): id is string => typeof id === 'string' && id.trim().length >= 1 && id.trim().length <= 128;
Try / catch
try {
return await stub.renameDevice(deviceId, name);
} catch (e) {
if (String(e).includes('device_id must be 1-128 characters')) return false;
throw e;
} Prevention
- Store the canonical registered device id and reuse it verbatim
- Trim ids and names in the UI before submitting
- Enforce the 1-128 char constraint wherever device ids are created
When it happens
Trigger: Renaming with an empty id after trimming, or an id longer than 128 chars (e.g. a full URL or concatenated token passed as the id).
Common situations: Client storing a prefixed/over-long identifier, UI sending an untrimmed whitespace-only id, schema change where device ids became longer after migration.
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
- canonical content
- device_limit_exceeded
- deviceId must be non-empty
- invalid_ops: device name must be at most 80 characters
- invalid_ops: deviceId must be 1-128 characters
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/bb3fc7a4e3a32d23.
Report an issue: GitHub.
Appendix: source
Thrown at workers/sync-hub/src/do/SyncHub.ts:623
connection_state: connected.has(row.device_id) ? "connected" as const : "disconnected" as const,
};
});
return {
protocol_version: 1,
user_id: userId,
epoch: this.meta("epoch"),
head_seq: head,
projected_seq: projected,
projection_lag_ops: decimalLag(head, projected),
sync_health: head === projected ? "healthy" : "projector_lagging",
devices,
};
}
renameDevice(deviceId: string, name: string): boolean {
const normalizedId = deviceId.trim();
const normalizedName = normalizeDeviceName(name);
if (normalizedId.length === 0 || normalizedId.length > 128) throw invalid("device_id must be 1-128 characters");
if (normalizedName === null) throw invalid("name must be 1-80 characters");
return this.ctx.storage.sql.exec(
"UPDATE devices SET name = ? WHERE device_id = ?",
normalizedName,
normalizedId,
).rowsWritten > 0;
}
// ---------------------------------------------------------------------
// Authoritative projection checkpoint and short per-user lease.
// ---------------------------------------------------------------------
acquireProjectionLease(targetSeq: string, now = Date.now()): ProjectionLease {
const target = assertCanonicalDecimal(targetSeq);
const head = this.headSeq();
if (compareCanonicalDecimals(target, head) > 0) throw projectionError("target_seq exceeds head_seq");
const projected = this.projectedSeq();
const existingToken = this.metaOptional("projection_lease_token");View on GitHub (pinned to d8bc9755e7)