{"record":{"id":"2312154e934b37e5","repo":"dmtrKovalenko/fff","slug":"grep-returned-null-result","errorCode":null,"errorMessage":"grep returned null result","messagePattern":"grep returned null result","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/fff-bun/src/ffi.ts","lineNumber":1100,"sourceCode":"  if (ctxAfterCount > 0) {\n    match.contextAfter = readCStringArray(read.ptr(pp, GM_CTX_AFTER), ctxAfterCount);\n  }\n  if (read.u8(pp, GM_IS_DEFINITION) !== 0) {\n    match.isDefinition = true;\n  }\n\n  return match;\n}\n\n/**\n * Parse an FffGrepResult from a raw FffResult pointer, then free native memory.\n */\nfunction parseGrepResult(resultPtr: Pointer | null): Result<GrepResult> {\n  const envelope = readResultEnvelope(resultPtr);\n  if (!(\"success\" in envelope)) return envelope;\n\n  if (envelope.handlePtr === 0) {\n    return err(\"grep returned null result\");\n  }\n\n  const hp = asPtr(envelope.handlePtr);\n  const count = read.u32(hp, GR_COUNT);\n  const totalMatched = read.u32(hp, GR_MATCHED);\n  const totalFilesSearched = read.u32(hp, GR_FILES_SEARCHED);\n  const totalFiles = read.u32(hp, GR_TOTAL_FILES);\n  const filteredFileCount = read.u32(hp, GR_FILTERED);\n  const nextFileOffset = read.u32(hp, GR_NEXT_OFFSET);\n  const regexErrPtr = read.ptr(hp, GR_REGEX_ERR);\n  const regexFallbackError = readCString(regexErrPtr) ?? undefined;\n  const itemsBase = read.ptr(hp, GR_ITEMS);\n\n  const items: GrepMatch[] = [];\n  for (let i = 0; i < count; i++) {\n    items.push(readGrepMatchStruct(itemsBase + i * GM_SIZE_OF));\n  }\n","sourceCodeStart":1082,"sourceCodeEnd":1118,"githubUrl":"https://github.com/dmtrKovalenko/fff/blob/7f8537e70f0ea1210f9acbbfc4640141105cdc78/packages/fff-bun/src/ffi.ts#L1082-L1118","documentation":"parseGrepResult read a success envelope from fff_live_grep/fff_multi_grep but the result handle pointer is 0, so there is no grep result structure to parse. The binding refuses to return a fake empty result and surfaces this error instead.","triggerScenarios":"Calling ffiGrep/ffiMultiGrep where the native grep call returns a success envelope with handlePtr === 0 — native allocation failure, destroyed instance, or an ABI/version mismatch in the grep result layout.","commonSituations":"Grep invoked right after destroy(); searching a directory that no longer exists with a mismatched native build; stale build artifact after upgrading.","solutions":["Verify the finder instance is still alive before invoking grep (guard with ensureAlive).","Rebuild the native library so the grep result ABI matches the bindings.","If it persists on a valid instance with existing files, report as a native-side bug."],"exampleFix":"// before\nconst r = ffiGrep(handle, pattern);\n// after\nif (handle === null) return err('finder destroyed');\nconst r = ffiGrep(handle, pattern);","handlingStrategy":"try-catch","validationCode":"if (handle === null) return err('finder destroyed before grep');","typeGuard":"function hasNativeHandle(f) { return f != null && typeof f.handle === 'object' && f.handle !== null; }","tryCatchPattern":"try { const r = await finder.grep(pattern); } catch (e) { if (e.message.includes('grep returned null result')) return emptyGrepResult(); }","preventionTips":["Never call grep after destroy(); cancel timers/handlers in teardown.","Confirm target paths exist before issuing grep.","Rebuild native artifacts after version bumps."],"tags":["ffi","null-pointer","bun","grep"],"backgroundTag":"null-argument","analyzedSha":"7f8537e70f0ea1210f9acbbfc4640141105cdc78","analyzedAt":"2026-09-10T07:26:53.407Z","contentChangedAt":"2026-09-10T07:26:53.407Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}