{"record":{"id":"9c4007b92d538a2d","repo":"thedotmack/claude-mem","slug":"invalid-claude-mem-worker-port-in-settings-json","errorCode":null,"errorMessage":"Invalid CLAUDE_MEM_WORKER_PORT in settings.json: ${rawPort}","messagePattern":"Invalid CLAUDE_MEM_WORKER_PORT in settings\\.json: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/export-memories.ts","lineNumber":26,"sourceCode":"import type {\n  ObservationRecord,\n  SdkSessionRecord,\n  SessionSummaryRecord,\n  UserPromptRecord,\n  ExportData\n} from './types/export.js';\n\nconst WORKER_FETCH_TIMEOUT_MS = 30_000;\n\nfunction parseWorkerPort(rawPort: unknown): number {\n  if (typeof rawPort !== 'string' || rawPort.trim() === '') {\n    throw new Error('Invalid CLAUDE_MEM_WORKER_PORT in settings.json: missing');\n  }\n\n  const normalized = rawPort.trim();\n  const port = Number.parseInt(normalized, 10);\n  if (!Number.isInteger(port) || port < 1 || port > 65535 || String(port) !== normalized) {\n    throw new Error(`Invalid CLAUDE_MEM_WORKER_PORT in settings.json: ${rawPort}`);\n  }\n  return port;\n}\n\nasync function fetchWithTimeout(url: string, init?: RequestInit): Promise<Response> {\n  const controller = new AbortController();\n  const timeout = setTimeout(() => controller.abort(), WORKER_FETCH_TIMEOUT_MS);\n\n  try {\n    return await fetch(url, {\n      ...init,\n      signal: controller.signal,\n    });\n  } catch (error) {\n    if (error instanceof Error && error.name === 'AbortError') {\n      throw new Error(`Worker request timed out after ${WORKER_FETCH_TIMEOUT_MS}ms: ${url}`);\n    }\n    throw error;","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/scripts/export-memories.ts#L8-L44","documentation":"Thrown by parseWorkerPort() after the value passes the non-empty-string check but fails strict numeric validation. The check requires parseInt to yield an integer in the range 1–65535 AND that String(port) exactly equals the trimmed input — the latter rejects leading zeros, trailing characters, signed values, and non-canonical forms. This prevents silently coercing garbage like '8080abc' into port 8080.","triggerScenarios":"CLAUDE_MEM_WORKER_PORT is set to a value like '0', '99999', '-5', '8080abc', '08080', '0x1f90', '8080 ', '8.0', or any value where Number.parseInt disagrees with the canonical decimal string. The String(port) !== normalized clause specifically catches leading-zero and trailing-suffix cases that parseInt alone would tolerate.","commonSituations":"Someone edited settings.json and quoted a port with a typo or a trailing newline. A port copied from a URL that included a path (e.g. ':44328/api'). A value written by tooling that appended a unit or comment. Leading zeros from a zero-padded config generator.","solutions":["Open ~/.claude-mem/settings.json and correct CLAUDE_MEM_WORKER_PORT to a plain decimal string in 1–65535 (e.g. \"44328\") with no spaces, signs, or leading zeros.","If the worker is running, read the actual port from the worker's startup log and copy that exact value.","Delete the key and restart the worker so it rewrites a clean value, then retry the export."],"exampleFix":"// before\n{ \"CLAUDE_MEM_WORKER_PORT\": \" 08080 \" }\n// after\n{ \"CLAUDE_MEM_WORKER_PORT\": \"8080\" }","handlingStrategy":"validation","validationCode":"function isValidPortLiteral(raw: unknown): raw is string {\n  if (typeof raw !== 'string') return false;\n  const n = raw.trim();\n  if (!/^\\d{1,5}$/.test(n)) return false;\n  const p = Number(n);\n  return p >= 1 && p <= 65535 && String(p) === n;\n}","typeGuard":"function isWorkerPort(v: unknown): v is string {\n  if (typeof v !== 'string') return false;\n  const n = v.trim();\n  if (!/^\\d+$/.test(n)) return false;\n  const p = Number.parseInt(n, 10);\n  return Number.isInteger(p) && p >= 1 && p <= 65535 && String(p) === n;\n}","tryCatchPattern":null,"preventionTips":["Write port values as plain decimal strings with no padding, signs, or leading zeros.","When writing settings programmatically, coerce via String(Number(value)) and range-check.","Add a JSON-schema check for settings.json that enforces a 1–65535 integer-string for CLAUDE_MEM_WORKER_PORT."],"tags":["config","validation","port","settings","export"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}