atuinsh/atuin · error

'{}' is a table; use a dotted key like '{}.key' to set a val

Error message

'{}' is a table; use a dotted key like '{}.key' to set a value within it

What it means

When setting a config key, atuin refuses to overwrite an existing TOML table (or inline table) with a scalar value. If the final segment of the dotted key currently holds a table, the command bails and tells you to append another segment so you set a value *inside* the table instead of replacing it.

Source

Thrown at crates/atuin/src/command/client/config.rs:346

    // Navigate/create intermediate tables
    for &part in &parts[..parts.len() - 1] {
        if !current.contains_key(part) {
            current.insert(part, Item::Table(Table::new()));
        }
        current = current
            .get_mut(part)
            .expect("just inserted or already exists")
            .as_table_like_mut()
            .ok_or_else(|| eyre::eyre!("'{}' exists but is not a table", part))?;
    }

    let last = *parts.last().unwrap();

    // Don't silently overwrite a table with a scalar value
    if let Some(existing) = current.get(last)
        && (existing.is_table() || existing.is_inline_table())
    {
        eyre::bail!(
            "'{}' is a table; use a dotted key like '{}.key' to set a value within it",
            key,
            key
        );
    }

    if let Some(item) = current.get_mut(last) {
        let mut value = value;
        if let Some(old_value) = item.as_value_mut() {
            // Preserve any commands attached to the old value.
            std::mem::swap(value.decor_mut(), old_value.decor_mut());
        }
        *item = Item::Value(value);
    } else {
        current.insert(last, Item::Value(value));
    }

    Ok(())

View on GitHub (pinned to c0c717ab04)

Solutions

  1. Add the leaf key: `atuin config set daemon.enabled true` instead of `atuin config set daemon true`.
  2. Check the existing structure first: `atuin config get --verbose <table>` or read ~/.config/atuin/config.toml.
  3. If replacing the whole table is truly intended, edit config.toml manually.
  4. Use tab completion or `atuin doctor` to discover valid nested keys.

Example fix

// before
atuin config set daemon true
// error: 'daemon' is a table; use a dotted key like 'daemon.key'...
// after
atuin config set daemon.enabled true
Defensive patterns

Strategy: validation

Validate before calling

# inspect whether the target key is a table before setting
atuin config get --verbose daemon || true
tomlq '.daemon | type' ~/.config/atuin/config.toml 2>/dev/null

Prevention

When it happens

Trigger: Running `atuin config set stats` (or any key like `sync`, `daemon`, `keys`) with a scalar value when that top-level key is a table in config.toml, e.g. `atuin config set daemon true`.

Common situations: Assuming a key is a plain value when it is actually a namespace; typos like `atuin config set sync true` instead of `atuin config set sync.records true`; migrating old flat settings into the new nested schema.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12). Data as JSON: /api/errors/c9df67f0013a2bb0. Report an issue: GitHub.