Skip to content

libra init fails with "no such table: config" when ~/.libra/libra.db lacks the legacy config table; the libra config --global hint cannot fix it #472

Description

@genedna

Summary

libra init fails with fatal: failed to read config 'init.defaultBranch': ... no such table: config when the database at ~/.libra/libra.db is missing the legacy config table. The failure is triggered by the legacy-table fallback in the config cascade reader, and the printed hint (libra config --global init.defaultBranch <name>) cannot fix the problem because it writes to a different database (~/.libra/config.db), while init fails earlier in the local-scope read.

Environment

  • libra 0.22.15 (installed at ~/.libra/bin/libra)
  • macOS 26 (darwin 25.6.0), arm64

Steps to reproduce

  1. Have a ~/.libra/libra.db that was created at some point without the legacy config table (all other tables present and fully migrated; see evidence below).
  2. From $HOME (or any non-repo directory under it), run:
$ libra init linked

Actual output

fatal: failed to read config 'init.defaultBranch': failed to query legacy config for 'init.defaultBranch' from database '/Users/eli/.libra/libra.db': Query Error: error returned from database: (code: 1) no such table: config: error returned from database: (code: 1) no such table: config

Hint: fix or remove the unreadable config with 'libra config --global init.defaultBranch <name>'

Running the suggested libra config --global init.defaultBranch main succeeds (verified: the row lands in ~/.libra/config.db), but re-running libra init still fails with the identical error.

Root cause

  1. resolve_initial_branch_name (src/command/init.rs:504) reads init.defaultBranch via read_cascaded_config_value_strict(LocalIdentityTarget::CurrentRepo, ...), which resolves scopes in order: local repo → global → system.
  2. Repository discovery (try_get_paths_full, src/utils/util.rs:625 + is_valid_storage_dir, src/utils/util.rs:160) walks up from cwd and accepts any directory containing a .libra/ that merely contains libra.db. The global libra home ~/.libra/ happens to contain libra.db, so from $HOME (or any non-repo subdirectory of it) the local config DB resolves to /Users/eli/.libra/libra.db.
  3. read_config_entry_from_db_path_case_insensitive (src/internal/config.rs:1896) queries config_kv first (table exists, no matching row), then falls back to the legacy config table. That table is missing from this DB, so the SQLite query errors out instead of being treated as "no legacy rows".
  4. In read_cascaded_config_value_strict (src/internal/config.rs:1371), local-scope errors propagate via ? — only the system scope is unconditionally skipped, and the global scope is skipped only for future-schema DBs (skip_global_scope_if_schema_future). So init hard-fails before the (healthy) global scope is ever consulted.
  5. The schema self-heal path apply_database_schema_upgrades (src/internal/db.rs:766) tops up config_kv, the AI projection tables, the operation tables, and runs the versioned migrations — but there is no ensure_config_schema equivalent for the legacy config table, so a DB missing only that table never recovers on open.

Additionally, global_config_path() (src/internal/config.rs:1257) points at ~/.libra/config.db, which is why the error hint's suggested command writes to a different file and can never fix this failure — the hint is misleading.

Evidence from the affected machine (read-only inspection)

~/.libra/libra.db:

  • Has config_kv, object_index, schema_versions (migrated up to 2026082401), AI/operation/agent tables — no config table.
  • config_kv has 0 rows; reference, reflog, object_index, agent_session, ai_thread all have 0 rows (the file is effectively an empty artifact of the home directory being adopted as a repo storage).

~/.libra/config.db (the actual global config DB):

  • Healthy: contains both config and config_kv, and after running the hinted command it correctly holds init.defaultBranch = main — yet init still fails, confirming the failure happens in the local scope.

Suggested fixes

  1. In read_config_entry_from_db_path_case_insensitive, treat a missing legacy config table as "no legacy rows" (e.g. probe with sqlite_schema_contains first, or map the no such table error to Ok(None)), matching the tolerant posture of the system scope.
  2. Add an ensure_config_schema step (analogous to ensure_config_kv_schema) to apply_database_schema_upgrades so DBs missing only the legacy table self-heal on open.
  3. Fix the InitError::ConfigRead hint: in this scenario libra config --global ... targets ~/.libra/config.db and cannot repair a broken ~/.libra/libra.db.
  4. Design question worth considering: ~/.libra (the global home: config.db, vault-keys/, bin/, …) currently satisfies is_valid_storage_dir because it contains libra.db, so any command run from $HOME without a nearer repository resolves the home as the enclosing repo and reads ~/.libra/libra.db as "local" config. Excluding the global home directory from repository discovery would prevent this whole class of accidents.

Workaround

Recreate the missing table with the canonical bootstrap schema (additive, no data risk):

sqlite3 ~/.libra/libra.db "CREATE TABLE IF NOT EXISTS config (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    configuration TEXT NOT NULL,
    name TEXT,
    key TEXT NOT NULL,
    value TEXT NOT NULL
);"

Alternatively, libra init linked -b main bypasses the config read for init only — but other commands that read other keys through the same DB will keep hitting the same error.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingvcs

Type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions