Troubleshooting¶
Start inside the intended brain. These commands inspect saved files and local history, without running programs or contacting providers:
bf --version
bf validate
bf status
Read the file, field or program the diagnostic names before retrying. Diagnostics go to stderr and never quote your content.
Find the right fix¶
| Symptom | First check | Next step |
|---|---|---|
bf: command not found |
Did uv finish installing BF? | Run uv tool update-shell, open a new shell and retry bf --version. |
| No brain, or the wrong one | Working directory and BF_BRAIN. |
Pass --brain ~/brain; see brain selection. |
pass --brain PATH or run inside the brain |
Did collect, run, channel, queue, update or watch run outside one? |
Run inside the brain or pass --brain PATH. Registration selects brains for retrieval only. |
… has no bf.yaml |
Does --brain, BF_BRAIN or the registry name a subfolder or parent? |
Name the brain's root folder, which holds bf.yaml, or create a brain with bf init. |
registered brain directory is absent … or bf.yaml is missing |
Did the brain move, or is its disk or share unmounted? | Restore it, run bf register at its new place or remove its entry; see registration. |
bf: invalid input: ARGUMENT: … |
The named argument in bf COMMAND -h. |
Correct that value and retry; see exit codes. |
| An option is unknown | bf --version and bf COMMAND --help. |
Match the docs to your version. |
bf.yaml declares version … |
The brain format in bf.yaml and evals/*.yaml. |
Apply the upgrade steps in the changelog. |
| A configuration field is rejected | The named file and field, or its line and column. | Fix its type, spelling or duplicate key; use the editor schema. |
… not found or unknown source, with did you mean …? |
The suggested name. | Read the suggestion, or search for the evidence. A missing section lists the note's sections. |
"valid":false |
Each problem's file and error. |
Repair them and validate again; see Check your brain. |
| Search misses a known answer | The exact note or record ref, and unmatched. |
Search with words from that evidence, without a scope; see search. |
A reply has problems or stale |
Skipped files, references or a busy writer. | Resolve them, or retry after the writer finishes. |
reference exists in several brains |
Several selected brains hold that ref. | Read the result's uri, a bf://NAME/... address. |
| A program fails | bf status and its logs/NAME.log. |
See a program fails, or an assistant fails. |
| A program never runs automatically | enabled, refresh and selectors. |
See updates do not run. |
"silent":true in bf status |
The source's changed and silent_after. |
Check the sensor's account, filter or query; see silent sources. |
| An assistant runs automatically | Its inputs and named schedules. | Remove the unwanted subscription or schedule, or set enabled: false. Inspect existing queued work separately. |
state directory … is inaccessible |
The named directory and XDG_STATE_HOME. |
Make it yours and writable, or set XDG_STATE_HOME; see local state. |
state directory may not contain symlinks |
Is ~/.local/state, XDG_STATE_HOME or its bf/ folder a link? |
Replace the link with a real folder, or set XDG_STATE_HOME to one; see local state. |
the search cache needs SQLite 3.35.0 … |
The SQLite version the message names. | Reinstall BF on a uv-managed Python. |
reading YAML needs PyYAML built with libyaml … |
bf --version and the Python uv chose for BF. |
Reinstall BF with a PyYAML wheel that bundles libyaml. |
| An agent cannot connect | The same read in your terminal. | Check absolute paths and restart the host; see MCP troubleshooting. |
bf mcp needs the mcp extra |
Did you install BF without the mcp extra? |
Reinstall BF with the extra; see MCP setup. |
Reinstall BF¶
If you use MCP, write 'brain-framework[mcp]' in place of brain-framework in the first two commands.
- SQLite too old:
uv tool install --reinstall --managed-python --python 3.14 brain-framework. - PyYAML without libyaml:
uv tool install --reinstall --python 3.14 brain-framework. - Missing
mcpextra: runuv tool install --python 3.14 'brain-framework[mcp]', then restart the host.
A program fails¶
Failed collection leaves saved records intact. bf status marks the program "failed":true, with its error, consecutive failures and log, such as logs/calendar.log. The log can hold provider output: read it locally and never paste it into a public issue.
Fix the cause, then rerun the program with bf collect SENSOR or bf run ROUTINE. Updates retry on their own after the failure backoff.
not an executable regular filefrombf validate: runchmod +xon the program, or put an interpreter in itscommand.is not a regular file or folder: a missing file or a typo. Behind an interpreter, as in[uv, run, --no-project, sensors/brief.py], validation checks only that the firstsensors/,routines/orchannels/path among the arguments exists.program was killed by SIGKILL: another process, such as the out-of-memory killer, ended the program.- Testing a fix:
bf collect SENSOR --dry-runexecutes the sensor and may contact its provider.bf update --dry-runonly lists due work.
A snapshot fails with snapshot would remove N of M records when it would empty its source, or remove more than half of it and more than 10 records. Check the account, folder and provider response. Do not delete stored records to make collection pass. When the removal is intended, accept it once with bf collect SENSOR --allow-removal.
An assistant fails¶
A failed assistant run keeps its queue state and any saved answer. Its log holds the harness's stderr.
To see what the harness receives, preview the expanded prompt:
- Add a temporary assistant that reuses the prompt file with
command: [cat]and noreply,inputs,postorschedules, such asprompt-check: {prompt: prompts/personal.md, command: [cat]}. - Run
bf run prompt-check --dry-run. To fill{{input}}, add--stdinand pipe a message. - Read the reply's
text: it is the expanded prompt. Nothing is recorded, queued or delivered. - Remove that assistant afterwards.
Do not swap the command or text of an assistant that has pending work, even for a moment: each job keeps the settings it was queued with. See configuration changes for what still runs and how to recover.
Common errors and replies:
assistant command must print one JSON object when text is set: withtextset, stdout must be one JSON object. Ask the harness for a single JSON result, such as--output-format json, not text or a stream of JSON lines. Or removetextto keep all of stdout as the reply.assistant reply has no text string at /…: the pointer names no string. Run the harness once by hand with the same output option and list the members of its JSON. Then pointtextat the reply, such as/resultfor Claude Code or/responsefor Antigravity.expanded assistant prompt exceeds 120000 bytes; shorten …: the prompt size limit applies on standard input too, not only to{{prompt}}in an argument. Shorten the prompt file or the piped input, and let the harness read evidence withbf read. A queued job keeps its template, so onlybf queue ID --cancelresolves it. A message's job blocks its conversation until then.the argument holding the prompt exceeds Linux's 128 KiB limit: the rest of that argument pushed it over Linux's bound. Shorten it, or drop{{prompt}}so the prompt arrives on standard input, if the harness reads it there.… configuration changed; restore it …: the job's settings no longer match. The assistant's prompt, harness or output settings, or thesendcommand of a channel its job delivers to, changed since queuing, or the assistant was removed or disabled. Restore them, then runbf queue ID --retry, or abandon the job withbf queue ID --cancel."status":"skipped"in abf updatereply: withoutjob, the active watch dispatcher owns automatic work. Withjob, another process runs that job, or itsskippedreason says it waits untilbf.yamlloads. Inspectbf queuefor failed or uncertain jobs. Schedule progress remains independent of direct runs.program exited with status …, with a sign-in error in the log: the harness is not signed in for the account and environment running BF. Sign in as that user. A service or timer gets only the variables its file sets, such asPATH, not your shell's.- The reply says the agent could not run
bf readorbf search: the harness cannot ask for approval without a terminal, or its--toolslist leaves outBash. Allow those read-only commands in its command, such as Claude Code's--allowedTools 'Bash(bf read *),Bash(bf search *)', or in its permission settings. KeepBashin any--toolslist. program timed out after …s: give the harness its own time limit belowtimeout, such as Antigravity's--print-timeout, and keep the prompt's task small.
Inspect bf queue for failed or uncertain assistant jobs:
- A saved answer resumes without rerunning the harness.
- An interrupted harness needs explicit review before
bf queue ID --retry, because tools might already have acted. - Delivery retry sends only the saved answer.
See assistant settings and queue recovery.
Queue and channel errors¶
PROMPT: cannot read assistant NAME's prompt; …: restore the prompt file or correctpromptinbf.yaml. The assistant's schedules wait meanwhile and start once it reads.assistant queue is full; …,admitted N of M messages: unfinished work fills the queue. Retry or cancel the failed and uncertain workbf queuelists. A read input catches up at its next poll, and a stream's provider redelivers.assistant queue lacks answer space for this job; …or… for this run, so it was cancelled; …: running jobs hold the space, and the job starts once they finish.bf runcancels its job instead, so run it again then.assistant NAME needs N MiB of queue space per answer, …: lower the assistant'smax_bytes(limits), then retry the job.assistant queue holds unresolved work admitted under this brain's previous path or name; …:bf statusalso reports it after a move or rename. Restore the previous path or name, resolve the work withbf queue, then move or rename again. A drained queue needs nothing: the nextbf queueor execution command rebinds it. Collection still works meanwhile.assistant queue predates this release; …: an earlier release created this queue.bf statusreports it too, and execution refuses it. Never delete it. Follow that upgrade's manual steps in the changelog, which resolve its work and update the queue in place. Resolving needs the previous release: reinstall it, such asuv tool install --python 3.14 'brain-framework==19.1.0', drain the queue, then upgrade again.unexpected assistant queue schema; …: another build created this queue, such as a pre-release one, andbf statusreports it too. Resolve its work with that build and back the queue up. Then move itsqueue.sqlite3out of theruntime/folder: the next execution command creates an empty queue. A queue updated by hand needs the full upgrade statement in the changelog.assistant queue holds an interrupted write; …: a BF process was killed while writing the queue. Runbf queue, or any execution command, to roll the write back. Keepqueue.sqlite3and its-journalfile together and delete neither.job is still running; …ordelivery is still being sent; …: another process, such asbf run,bf updateor watch, still runs that attempt. Let it finish or stop that process, then run the command again. An attempt whose process ended is recorded first, so--retryor--cancelthen resolves it.stream frame exceeded max_bytes: the adapter printed a line longer thanchannels.NAME.stream.max_bytes. Raise a lowered limit, up to the 1 MiB default, or print compact UTF-8. Then restart watch: the provider redelivers the message. No valid envelope exceeds 1 MiB, so beyond it, fix the adapter's framing.channel NAME: more than 1000 messages fall within one second; …: a read input caught up in parts down to one second, and that second still held more than one batch. An adapter that gives a backlog one timestamp causes this. Give each message its provider time, or read the channel with astreaminput. The parts admitted before are kept.assistants.NAME.inputs: unknown channel X: declareXunderchannels:or correct the name, here or underpost.channel X requires MODEorrequires sendasks for that capability: an input channel needssendto answer its messages.
Updates do not run¶
bf update --dry-run
bf status
A sensor or routine runs automatically only when it is enabled, has a nonzero refresh, is due and matches the selectors. Timing and health gives the rule.
- The dry run's
manuallist names enabled sensors and routines withrefresh: 0, and assistants without schedules or inputs. - Watch must stay open, in a terminal or as a service, or a timer must be active on a running machine; see service behavior and host lifecycle.
- Check health on the collecting machine: a teammate's clone shares the records, not the run history.
Recover the cache or an interrupted write¶
While an interrupted record write awaits recovery, bf status reports "pending_transaction":true, a stale or missing cache and a problem naming the command to run. Let active collection finish, then:
bf build
bf validate
bf status --check
bf build recovers the interrupted write and rebuilds the cache from the files:
- Before replacing records, a write keeps hard-link backups of them in
memories/.pending/. Keep that folder until recovery succeeds. - Recovery restores only the files that write changed.
bf collect,bf updateandbf watchalso recover it before writing. Search and read never do.
If bf build refuses the journal itself, keep what it holds:
- For
unexpected file in memories/.pending, move the file it names out of the brain and runbf buildagain. - For any other refusal that names
memories/.pending, move the wholememories/.pendingfolder out of the brain. Examples areinvalid memories/.pending manifest,duplicate paths in memories/.pending manifestor a missing or oversized.beforebackup. Runbf buildandbf validate, then collect the source its manifest names again: each record file is whole, but that collection may be half applied.
How the rebuild behaves:
- It fills
.bf/index.sqlite.newbeside the live cache and replaces the cache when complete, so searches keep answering meanwhile. - A rebuild killed before it finishes leaves that file. The next search, read or status removes it once no build is running.
bf buildexits 1 when itsskippedcount shows unreadable files;bf validatenames them.- A damaged cache is discarded and rebuilt on its own.
- An exact read that meets an active write returns within about 3 seconds, marked
stale: retry it for the final content.
Files¶
| If you see… | What to do |
|---|---|
| A record file edited by hand still answers with its old text | Run bf build. Searches keep the cached copy because an edit in place leaves the folder unchanged; collection renames records into place. |
A skipped link or special file in problems |
Replace a link with the file or folder it points to, and a special file with a regular file, inside the brain. BF never follows links. |
unreadable folder or inaccessible file or folder |
Restore read and search permission, such as with chmod -R u+rwX memories, or move the folder out of the brain. The rest of the brain keeps answering. |
unreadable file; retried next time |
A read failed, such as on a network or sync mount. The next search, read or status tries again; if it persists, check the mount or disk. |
| A file name that is not valid UTF-8, or holds a backslash or control character | Rename the file, shown with escapes such as \xNN, as for a Latin-1 name from an old archive. |
expected a folder; replace the file with a folder |
A file stands where projects/, concepts/, actions/ or memories/ belongs. Move it out of the brain, create the folder, then run bf validate. |
expected a directory; symlinks and special files are not followed |
Replace the linked folder with a regular one. |
note is not UTF-8 |
Convert the named note to UTF-8. |
| Git conflict markers at the start of a line | Reconcile both revisions. The note stays unsearchable until then, even inside a code block. |
A skipped record that you fix in place, or whose permissions you restore, is read again on its own.
Writes are atomic:
- A write killed before its rename, by BF or the bf-use guarded-write helper, leaves a
.write-HEXfile beside its target. - The next write of a record source removes its own.
bf validatewarns about those inprojects/,concepts/andactions/(an interrupted write left this temporary file; delete it). None blocks an action routine.- An editor's lock files, named
.#NAME, are ignored. - A file removed during a scan, as by an editor's save, is indexed at the next refresh.
Report a reproducible problem¶
Include the BF version, operating system, the failing command with private paths replaced, its exit code, and expected versus observed behavior. Reproduce it with a small fictional note or record; omit private passages, credentials and logs. Use GitHub issues for bugs and the private reporting instructions for suspected vulnerabilities.