{"record":{"id":"b8d1ebed1746f473","repo":"dmtrKovalenko/fff","slug":"unsupported-fffcreateoptions-version-library-u","errorCode":null,"errorMessage":"Unsupported FffCreateOptions version {} (library understands up to {})","messagePattern":"Unsupported FffCreateOptions version (.+?) \\(library understands up to (.+?)\\)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fff-c/src/lib.rs","lineNumber":189,"sourceCode":"/// pointer. New fields are only appended; older `version` values keep working.\n/// FFI bindings needing struct-by-value should use [`fff_create_instance_with_value`].\n///\n/// `opts.base_path` is required (non-NULL, non-empty). Zero `cache_budget_*`\n/// values are auto-computed from repo size after the initial scan.\n///\n/// ## Safety\n/// * `opts` must be a valid pointer to an `FffCreateOptions` whose `version`\n///   is in the range `1..=FFF_CREATE_OPTIONS_VERSION`.\n/// * All string pointers inside `opts` must be valid null-terminated UTF-8\n///   or NULL.\n#[unsafe(no_mangle)]\npub unsafe extern \"C\" fn fff_create_instance_with(opts: *const FffCreateOptions) -> *mut FffResult {\n    if opts.is_null() {\n        return FffResult::err(\"opts is null\");\n    }\n    let opts = unsafe { &*opts };\n    if opts.version == 0 || opts.version > FFF_CREATE_OPTIONS_VERSION {\n        return FffResult::err(&format!(\n            \"Unsupported FffCreateOptions version {} (library understands up to {})\",\n            opts.version, FFF_CREATE_OPTIONS_VERSION\n        ));\n    }\n\n    let base_path_str = match unsafe { cstr_to_str(opts.base_path) } {\n        Some(s) if !s.is_empty() => s.to_string(),\n        _ => return FffResult::err(\"opts.base_path is null or empty\"),\n    };\n\n    if let Some(log_path) = unsafe { optional_cstr(opts.log_file_path) } {\n        let level = unsafe { optional_cstr(opts.log_level) };\n        if let Err(e) = fff::log::init_tracing(log_path, level, None) {\n            return FffResult::err(&format!(\"Failed to init tracing: {}\", e));\n        }\n    }\n\n    let frecency_path = unsafe { optional_cstr(opts.frecency_db_path) }.map(|s| s.to_string());","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/dmtrKovalenko/fff/blob/7f8537e70f0ea1210f9acbbfc4640141105cdc78/crates/fff-c/src/lib.rs#L171-L207","documentation":"The FffCreateOptions struct is versioned for ABI stability. If opts.version is 0 (uninitialized struct) or greater than FFF_CREATE_OPTIONS_VERSION (built against a newer header than the loaded library), creation is refused. This prevents misinterpreting a struct layout the library does not understand.","triggerScenarios":"Passing a zero-initialized FffCreateOptions without setting version; loading an older shared library with options built from a newer fff-c header (version > FFF_CREATE_OPTIONS_VERSION).","commonSituations":"Upgrading the npm/package bindings without reloading/rebuilding the native library (stale .so/.dll on disk); memset(0) structs where version was forgotten; mixing headers from different versions in one build.","solutions":["Set opts.version = FFF_CREATE_OPTIONS_VERSION from the header you compile against.","Rebuild/reinstall the native library so it matches the bindings' expected version.","Ensure only one version of the fff shared library is on the library path (check with ldd / LD_LIBRARY_PATH).","Zero-initialized structs must explicitly set the version field."],"exampleFix":"// before\nFffCreateOptions opts = {0}; // version left at 0\n// after\nFffCreateOptions opts = {0};\nopts.version = FFF_CREATE_OPTIONS_VERSION;\nopts.base_path = \"/repo\";","handlingStrategy":"validation","validationCode":"if (!opts.version || opts.version > FFF_CREATE_OPTIONS_VERSION) throw new Error(`unsupported FffCreateOptions version ${opts.version}`);","typeGuard":"function hasSupportedVersion(o) { return Number.isInteger(o.version) && o.version >= 1 && o.version <= FFF_CREATE_OPTIONS_VERSION; }","tryCatchPattern":"const res = fff_create_instance_with(opts);\nif (!res.ok && /Unsupported FffCreateOptions version/.test(res.error)) {\n  reloadNativeLibrary(); // rebuild/reinstall to match versions\n  retry();\n}","preventionTips":["Always set version = FFF_CREATE_OPTIONS_VERSION from the compiled header.","Keep bindings and native library versions in lockstep.","Never hand zero structs without setting version.","After upgrades, confirm the loaded .so/.dll is the new build."],"tags":["ffi","abi","versioning","rust"],"backgroundTag":"unsupported-config-value","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"}