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
- Add the leaf key: `atuin config set daemon.enabled true` instead of `atuin config set daemon true`.
- Check the existing structure first: `atuin config get --verbose <table>` or read ~/.config/atuin/config.toml.
- If replacing the whole table is truly intended, edit config.toml manually.
- 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
- Read the existing config.toml structure before running `config set` on top-level names.
- Assume namespace-looking names (daemon, sync, stats, keys) are tables.
- Always set a leaf key one level deeper than a table.
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
- Config key must be non-empty and must not contain whitespace
- empty config key
- Failed to deserialize theme: {}
- Failed to read from input
- failed to set absolute path override for {key}
AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12).
Data as JSON: /api/errors/c9df67f0013a2bb0.
Report an issue: GitHub.