ruvnet/RuView · error · anyhow::Error

invalid automations file {}: {e}

Error message

invalid automations file {}: {e}

What it means

Anyhow error wrapping a serde_yaml failure: the file given via --automations was read successfully (tokio::fs::read_to_string) but could not be deserialized into Vec<homecore_automation::Automation>. The message includes the path and the underlying serde error (line/column and the field that failed), and none of the automations load because parsing aborts before the register loop.

Source

Thrown at v2/crates/homecore-server/src/main.rs:294

            limits: homecore_plugins::DiscoveryLimits::default(),
        },
    )
    .await?;

    // ── 4. Automation engine ────────────────────────────────────────
    // Construct AND start the engine (HC-WS-03, ADR-161). `start()`
    // spawns the state-change event loop + the 1 Hz wall-clock timer
    // task so state/numeric/event AND time triggers all fire. The
    // engine is kept alive for the process lifetime (it is moved into a
    // long-lived binding); its background tasks run until the HomeCore
    // broadcast channel closes at shutdown. No automations are loaded at
    // boot yet (YAML loader is P-next); integrations register via
    // `engine.register(..)`.
    let automation_engine = AutomationEngine::new(hc.clone());
    if let Some(path) = &cli.automations {
        let raw = tokio::fs::read_to_string(path).await?;
        let automations: Vec<homecore_automation::Automation> = serde_yaml::from_str(&raw)
            .map_err(|e| anyhow::anyhow!("invalid automations file {}: {e}", path.display()))?;
        for automation in automations {
            automation_engine.register(automation);
        }
    }
    let _automation_task = automation_engine.start();
    info!(
        "Automation engine started ({} automations registered) — \
         state/numeric/event + time triggers active",
        automation_engine.len()
    );

    // ── 5. Assist pipeline ──────────────────────────────────────────
    // ── 6. HAP bridge surface ───────────────────────────────────────
    // ── 7. REST + WS API ────────────────────────────────────────────
    // Token provisioning closes audit findings HC-01/HC-02. If
    // HOMECORE_TOKENS is set in the env, populate the store from
    // its comma-separated list. Otherwise fall back to DEV mode
    // (warn-on-each-request) so existing smoke tests still work.

View on GitHub (pinned to 4685618388)

Solutions

  1. Read the {e} portion of the message -- serde_yaml names the line/column and the offending field; fix that spot first
  2. Validate the file parses before startup: python -c 'import yaml,sys; yaml.safe_load(open(sys.argv[1]))' for syntax, then check structure against the Automation definition
  3. Ensure the top level is a YAML sequence of automation mappings matching the current homecore-automation schema (field names and types)
  4. After a version upgrade, re-check the automation file format against the release's documented schema

Example fix

# before (automations.yaml)
automation:
  - name: lights-off
    # error: invalid automations file automations.yaml: invalid type: map, expected a sequence

# after (automations.yaml)
- name: lights-off
  trigger: { state: { entity: light.desk, to: 'off' } }
  action: { service: light.turn_off, target: light.desk }
Defensive patterns

Strategy: validation

Validate before calling

# preflight: syntax + shape check before handing the file to the server
python3 - <<'EOF'
import yaml, sys
docs = yaml.safe_load(open(sys.argv[1]))
assert isinstance(docs, list), 'automations file must be a top-level YAML list'
for a in docs:
    assert isinstance(a, dict) and 'name' in a, f'bad automation entry: {a!r}'
print('automations OK:', len(docs))
EOF
homecore-server --automations automations.yaml

Try / catch

let automations: Vec<Automation> = match serde_yaml::from_str(&raw) {
    Ok(v) => v,
    Err(e) => {
        tracing::error!("invalid automations file {path}: {e}; starting with 0 automations");
        Vec::new()
    }
};

Prevention

When it happens

Trigger: YAML syntax errors (tabs, bad indentation, missing colon); schema mismatches -- top level is a mapping instead of a list, automation entries use wrong or renamed field names, or a value has the wrong type for the Automation struct.

Common situations: Hand-edited automation files introducing stray characters; upgrades that renamed Automation fields while old YAML keeps the previous names; copying examples from a different version of the project; editors inserting tabs.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/e64ce779479922d0. Report an issue: GitHub.