{"record":{"id":"a7e434e20ae03580","repo":"thedotmack/claude-mem","slug":"storeobservation-requires-a-non-empty-title","errorCode":null,"errorMessage":"storeObservation requires a non-empty title","messagePattern":"storeObservation requires a non-empty title","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/services/sqlite/SessionStore.ts","lineNumber":3039,"sourceCode":"      facts: string[];\n      narrative: string | null;\n      concepts: string[];\n      files_read: string[];\n      files_modified: string[];\n      agent_type?: string | null;\n      agent_id?: string | null;\n      metadata?: string | null;\n    },\n    promptNumber?: number,\n    discoveryTokens: number = 0,\n    overrideTimestampEpoch?: number,\n    generatedByModel?: string\n  ): { id: number; createdAtEpoch: number } {\n    // storeObservations skips empty-title rows, which would leave no id to return here.\n    // This wrapper stores exactly one observation, so require a title up front rather than\n    // returning an undefined id.\n    if (!observation.title || observation.title.trim() === '') {\n      throw new Error('storeObservation requires a non-empty title');\n    }\n\n    const result = this.storeObservations(\n      memorySessionId,\n      project,\n      [observation],\n      null,\n      promptNumber,\n      discoveryTokens,\n      overrideTimestampEpoch,\n      generatedByModel\n    );\n\n    return { id: result.observationIds[0], createdAtEpoch: result.createdAtEpoch };\n  }\n\n  storeSummary(\n    memorySessionId: string,","sourceCodeStart":3021,"sourceCodeEnd":3057,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/sqlite/SessionStore.ts#L3021-L3057","documentation":"storeObservation is a single-row wrapper around storeObservations. storeObservations silently skips rows with empty titles, which would leave the wrapper with no inserted id to return; to keep its non-nullable {id, createdAtEpoch} contract, it validates the title up front and throws instead.","triggerScenarios":"Calling SessionStore.storeObservation(memorySessionId, project, observation) where observation.title is undefined, null, an empty string, or a whitespace-only string (e.g. title.trim() === '').","commonSituations":"Building an observation object programmatically where the title extraction failed (e.g. summarizer returned nothing, a hook passed a prompt with no content), or deserializing records from an older DB/export where the title field was optional.","solutions":["Set a non-empty observation.title before calling storeObservation (e.g. derive from content or use a placeholder).","If the title is genuinely optional, call storeObservations with a one-element array instead and check whether an id was returned.","Add a caller-side guard that falls back to a default title when the source text is empty."],"exampleFix":"// before\nawait store.storeObservation(sessionId, project, { title, content });\n// after\nawait store.storeObservation(sessionId, project, {\n  title: title && title.trim() ? title : content.slice(0, 80) || 'untitled observation',\n  content\n});","handlingStrategy":"validation","validationCode":"if (!observation.title || observation.title.trim() === '') {\n  throw new Error('Cannot store observation without a title');\n}\nawait store.storeObservation(sessionId, project, observation);","typeGuard":"function hasTitle(o: { title?: string }): o is { title: string } {\n  return typeof o.title === 'string' && o.title.trim() !== '';\n}","tryCatchPattern":null,"preventionTips":["Validate observation fields at construction time, not at the store boundary.","Default the title to a content-derived or placeholder string when sources are empty.","Keep title required in the observation TypeScript type so it cannot be omitted."],"tags":["validation","sqlite","empty-string"],"backgroundTag":"empty-required-field","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"}