{"record":{"id":"8644594b1af14e42","repo":"thedotmack/claude-mem","slug":"failed-to-parse-transcript-line-non-error-thrown","errorCode":null,"errorMessage":"Failed to parse transcript line (non-Error thrown)","messagePattern":"Failed to parse transcript line \\(non-Error thrown\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/transcripts/watcher.ts","lineNumber":315,"sourceCode":"\n  private async handleLine(\n    line: string,\n    watch: WatchTarget,\n    schema: TranscriptSchema,\n    filePath: string,\n    sessionIdOverride?: string | null\n  ): Promise<void> {\n    try {\n      const entry = JSON.parse(line);\n      await this.processor.processEntry(entry, watch, schema, sessionIdOverride ?? undefined);\n    } catch (error: unknown) {\n      if (error instanceof Error) {\n        logger.debug('TRANSCRIPT', 'Failed to parse transcript line', {\n          watch: watch.name,\n          file: basename(filePath)\n        }, error);\n      } else {\n        logger.warn('TRANSCRIPT', 'Failed to parse transcript line (non-Error thrown)', {\n          watch: watch.name,\n          file: basename(filePath),\n          error: String(error)\n        });\n      }\n    }\n  }\n\n  private extractSessionIdFromPath(filePath: string): string | null {\n    const match = filePath.match(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i);\n    return match ? match[0] : null;\n  }\n}\n","sourceCodeStart":297,"sourceCodeEnd":329,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/transcripts/watcher.ts#L297-L329","documentation":"handleLine wraps transcript-line parsing in a try/catch; when the thrown value is not an Error instance (e.g. a string or object was thrown), it logs a warn instead of a debug and stringifies the thrown value. Parsing of that line is aborted but the watcher keeps running.","triggerScenarios":"tailer -> handleLine on a transcript line whose parser throws a non-Error value — malformed/foreign JSONL content, a parser library that throws strings, or third-party code throwing plain objects.","commonSituations":"Corrupted or hand-edited transcript JSONL files; logs written by another tool that claude-mem's parser chokes on; a parser bug that throws `throw 'unexpected token'`.","solutions":["Inspect the `error` field (String(error)) to identify the malformed line and the underlying message.","Fix or remove the corrupted transcript line/file that triggers the parse failure.","Upgrade claude-mem — parsers throwing non-Errors is usually fixed upstream.","If caused by a third-party parser dependency, pin/upgrade that dependency so it throws proper Errors."],"exampleFix":"// before (third-party parser)\nthrow 'bad line'\n// after\nthrow new Error('bad line')","handlingStrategy":"type-guard","validationCode":"if (typeof line !== 'string' || line.trim() === '') return;\ntry { JSON.parse(line); } catch { console.warn('Non-JSONL line in transcript'); }","typeGuard":"function isError(e: unknown): e is Error {\n  return e instanceof Error;\n}","tryCatchPattern":"try {\n  parseTranscriptLine(line);\n} catch (error) {\n  const detail = error instanceof Error ? error.stack : String(error);\n  logger.warn('parse failed', { detail });\n}","preventionTips":["Never throw bare strings/objects from parsers — always throw Error","Validate JSONL files before pointing a watch at them","Keep transcript files from other tools out of watched directories"],"tags":["parsing","transcripts","error-handling"],"backgroundTag":"json-parse-error","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}