dmtrKovalenko/fff · error
No watch callback registered. Call fff_set_watch_callback…
Error message
No watch callback registered. Call fff_set_watch_callback first.
What it means
fff_watch delivers file-system events by invoking a callback registered earlier via fff_set_watch_callback. If no callback was registered on this instance, the watch cannot report events, so the call fails immediately instead of watching silently.
Solutions
- Call fff_set_watch_callback(handle, cb, user_data) before any fff_watch call on the instance.
- Register the callback at instance-creation time so it is always present.
- Check the order of your init code: create instance → set callback → start watch.
Example fix
// before fff_watch(inst, NULL, &opts); // fails: no callback // after fff_set_watch_callback(inst, on_events, NULL); fff_watch(inst, NULL, &opts);
Defensive patterns
Strategy: validation
Validate before calling
if (!watchCallbackRegistered) throw new Error('call fff_set_watch_callback before fff_watch'); Type guard
function canWatch(inst) { return inst && inst.watchCallbackRegistered === true; } Try / catch
try { fffWatch(pattern, opts); } catch (e) { if (String(e).includes('No watch callback')) { fffSetWatchCallback(cb); fffWatch(pattern, opts); } } Prevention
- Register the watch callback immediately after instance creation.
- Centralize instance setup so callback registration cannot be skipped.
- Re-register the callback whenever the instance is recreated.
When it happens
Trigger: Calling fff_watch or fff_watch_args on an instance without first calling fff_set_watch_callback for that same instance; calling on a freshly created instance; or after the callback slot was cleared/replaced.
Common situations: New developers wiring fff_watch without the registration step; high-level wrappers that register the callback only in some code paths; instance recreated but callback registration skipped.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- ignore_count > 0 but ignore is NULL
- ignore entry is NULL or invalid UTF-8
- Pattern is not valid UTF-8
- watch callback has been closed
- watch callback must be a function
AI-assisted analysis of dmtrKovalenko/fff@7f8537e70f (2026-09-10).
Data as JSON: /api/errors/8b5de07d5006818c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fff-c/src/watch.rs:194
let inst = match unsafe { instance_ref(fff_handle) } {
Ok(i) => i,
Err(e) => return e,
};
// NULL pattern = watch the entire indexed tree ("" in core).
let pattern_str = if pattern.is_null() {
""
} else {
match unsafe { crate::cstr_to_str(pattern) } {
Some(s) => s,
None => return FffResult::err("Pattern is not valid UTF-8"),
}
};
let options = match unsafe { watch_options_from_ffi(opts) } {
Ok(o) => o,
Err(e) => return e,
};
if inst.watch_callback.get().is_none() {
return FffResult::err("No watch callback registered. Call fff_set_watch_callback first.");
}
let slot = Arc::clone(&inst.watch_callback);
let result = inst.picker.watch(pattern_str, options, move |id, events| {
if let Some((cb, user_data)) = slot.get() {
let batch = batch_into_raw(events);
unsafe { cb(id.0, batch, user_data) };
}
});
match result {
Ok(id) => FffResult::ok_int(id.0 as i64),
Err(e) => FffResult::err(&format!("Failed to subscribe: {}", e)),
}
}
/// [`fff_watch`] adapter with flattened options, for FFI libraries that cannot
/// marshal pointer arrays inside structs (e.g. Node's `ffi-rs`).View on GitHub (pinned to 7f8537e70f)