astrid-runtime/astrid · error
existing [security.capsule_local_egress].{capsule_id} is not
Error message
existing [security.capsule_local_egress].{capsule_id} is not an array What it means
record_local_egress parses the operator's config file with toml_edit and inserts host arrays under [security.capsule_local_egress].<capsule_id>. If the key already exists but its value is not a TOML array (e.g. a string or inline table), the code cannot append ports and bails with this message. It protects the config from being silently overwritten with a wrong type.
Source
Thrown at crates/astrid-cli/src/commands/capsule/local_egress.rs:155
toml_edit::DocumentMut::new()
};
// Navigate / create `[security.capsule_local_egress]`.
let security = doc["security"].or_insert(toml_edit::table());
if let Some(t) = security.as_table_mut() {
// Keep the nested table from being rendered inline.
t.set_implicit(true);
}
let egress = doc["security"]["capsule_local_egress"].or_insert(toml_edit::table());
if let Some(t) = egress.as_table_mut() {
t.set_implicit(true);
}
let list = doc["security"]["capsule_local_egress"][capsule_id].or_insert(
toml_edit::Item::Value(toml_edit::Value::Array(toml_edit::Array::new())),
);
let Some(arr) = list.as_array_mut() else {
anyhow::bail!("existing [security.capsule_local_egress].{capsule_id} is not an array");
};
// Idempotent: skip if already present (case-insensitive host match handled
// by the host enforcement; here exact-string is enough for the operator
// file's own dedup).
let already = arr
.iter()
.any(|v| v.as_str().is_some_and(|s| s.eq_ignore_ascii_case(entry)));
if !already {
arr.push(entry);
}
if let Some(parent) = config_path.parent() {
std::fs::create_dir_all(parent).with_context(|| format!("create {}", parent.display()))?;
}
write_atomic(config_path, doc.to_string().as_bytes())
.with_context(|| format!("write {}", config_path.display()))
}View on GitHub (pinned to affd8760f4)
Solutions
- Open the config file and change the security.capsule_local_egress.<capsule_id> entry to a TOML array of strings, e.g. hosts = ["example.local"].
- Remove the malformed key and re-run the command so it recreates the array correctly.
- Validate the TOML file (e.g. with a TOML linter) after manual edits before running capsule commands.
Example fix
// before (config.toml) [security.capsule_local_egress] my-capsule = "api.local, db.local" // after [security.capsule_local_egress] my-capsule = ["api.local", "db.local"]
Defensive patterns
Strategy: validation
Validate before calling
let cfg: toml::Value = toml::from_str(&std::fs::read_to_string(path)?)?;
let bad = cfg.get("security")
.and_then(|s| s.get("capsule_local_egress"))
.and_then(|e| e.get(capsule_id))
.map(|v| !v.is_array())
.unwrap_or(false);
if bad { eprintln!("fix [security.capsule_local_egress].{capsule_id}: must be an array"); } Type guard
fn is_host_array(v: &toml::Value) -> bool {
v.as_array().map_or(false, |a| a.iter().all(|x| x.is_str()))
} Try / catch
match record_local_egress(...).await {
Err(e) if e.to_string().contains("is not an array") => {
// back up config, rewrite the key as an array, retry
}
r => r?,
} Prevention
- Hand-edit egress lists only as TOML arrays of strings.
- Run a TOML validator after manual config edits.
- Keep one writer (the CLI) for this config section to avoid shape drift.
When it happens
Trigger: Running a capsule command that records local egress hosts when the config already defines security.capsule_local_egress.<capsule_id> as a non-array TOML value (string, integer, table).
Common situations: Hand-edited config where a list was written as a quoted string ('host1, host2') or as an inline table; an older tool version wrote a different shape; copy-pasting config snippets with mismatched types.
Related errors
- Cargo include optional must be a boolean in {}
- Cargo include table must contain a string path in {}
- Cargo rustflags array contains a non-string value in {}
- Capsule.toml has no package.name
- Capsule.toml has no package.version
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/b52d8c650b5a59c3.
Report an issue: GitHub.