Common Issues
The quickest fixes for the most frequent problems.
Licence gate failures
Symptoms: Boot fails with No carrier licence found at <path>. A valid licence file is required to start the platform. Install a licence at $HOZIRON_HOME/licence.json. — or, at invocation time, No carrier licence loaded — all model invocations require a valid licence. The licence encodes contracted workflow budgets and provider entitlements.
The platform requires a valid carrier licence to start the routing gateway; without one, model invocations are blocked entirely (hoziron-cli licence status reports "status": "no_licence", "enforcement": "all_blocked").
Fix: Provision a real licence file at $HOZIRON_HOME/licence.json (default ~/.hoziron/licence.json). There is exactly one licensing path — no environment variable, test flag, or config option bypasses it. If you're issuing licences yourself (design-partner/internal tooling), see xtask licence issue; otherwise obtain one from your Hoziron account team.
hoziron-cli licence status --json
An expiring/expired licence shows "status": "expiring_soon" or "status": "expired" in licence status — renew before expiry; the platform does not grant a grace period past expires_at.
Auth posture gate refuses to start
Symptoms: A surface (api/mcp/dashboard/registry) refuses to boot with Refusing to start <surface>: auth.mode="disabled" while bound to network-reachable address '<addr>'. Set auth.mode to "local" or "oidc", bind to loopback for dev, or set auth.allow_insecure_no_auth=true to accept the risk (warns on every boot).
The address named in the error is that surface's effective listen address — its own [surfaces.<name>].listen if it's a main route, or its mount target's if it's mounted (e.g. mcp mounted on api is gated against api's bind address). dashboard is gated the same way as api/mcp — it shares the identical [auth]/key-store/OIDC trust model, so leaving it unauthenticated on a network-reachable bind is refused just like the others.
This is a deliberate boot-time safety check (Issue #512/#521): auth.mode defaults to disabled, which is fine for a single-user loopback dev box but must never silently expose a control plane on a network-reachable bind address.
Fix:
- Preferred: set
auth.mode = "local"(API keys) or"oidc"in config. - Local dev only: bind to a loopback address (
127.0.0.1:...,::1:...,localhost:..., orunix://...) — the gate only fires on non-loopback binds. - Explicit risk acceptance (not recommended outside throwaway environments):
auth.allow_insecure_no_auth = true— this still boots with auth disabled and logs aSECURITY:warning on every startup.
Config validation errors on boot
Symptoms: Boot or hoziron-cli config set/unset fails with a ValidationError/InitError naming a specific field, e.g. provider 'anthropic': invalid api_key_env '...', or server.cors.allowed_origins must not be empty when CORS is configured.
PlatformConfig::validate() (the single validation entry point — a previous, lighter validate_for_config_write() used by hoziron-cli config set/unset was collapsed into it) checks the full provider/model inventory, api_key_env naming, and [server.cors]. It does not know about [surfaces.*] (listen/mount/tls/allowed_ips/limits) — those fields, and the topology/auth-posture checks below, belong to bin/hoziron-server's own config struct and only get validated at real server boot, not by hoziron-cli config set/get/unset (a pure CLI edit against PlatformConfig's view of the file).
Fix:
# Show current config
hoziron-cli config show
# Fix a scalar field PlatformConfig knows about
hoziron-cli config set server.cors.allowed_origins '["https://dashboard.company.com"]'
# surfaces.* fields (listen, mount, tls, allowed_ips, limits) aren't
# validated by `hoziron-cli config set` — edit config.toml directly and let
# `hoziron-server` catch topology/hardening mistakes at boot instead
hoziron-cli config edit
The error always names the offending field ("field" detail key) — fix that field and re-run. For a surfaces.* topology or hardening error (e.g. surfaces.mcp: cannot set both listen and mount, or surfaces.api: allowed_ips is set on a unix:// listen address), the message comes from hoziron-server at boot, not from hoziron-cli config set — see TLS and networking for the full validation rules.
Daemon won't start — port in use
# Find what's using port 4200
lsof -i :4200
# Kill it, or use a different port
hoziron-server --api-listen 0.0.0.0:4201
Permission denied in container
The container runs as UID 65532 (distroless nonroot). Ensure the volume is writable:
# Docker
docker run -v hoziron-data:/data ...
# Or with explicit ownership
docker run -v ./local-data:/data --user 65532:65532 ...
If your container platform manages volume ownership itself, set it to group 65532 so the container's UID can write to the mounted volume.
Provider key not working
# Test the key
hoziron-cli config test-key anthropic
# Verify the env var is set
echo $ANTHROPIC_API_KEY
# Re-set it
hoziron-cli config set-key anthropic
Keys are resolved at request time — if you changed the env var, restart the daemon if it was set before the process started.
Agent won't respond to messages
Check the agent's current state — the lifecycle has exactly two states, Suspended and Running:
hoziron-cli agent status <agent-id>
If it's Suspended, activate it:
hoziron-cli agent activate <agent-id>
Activation is gate-checked (ADR-056): it fails if any competency the agent has equipped declares a contract with no installed provider. See agent troubleshooting for the full activation-gate error and fix.
"Cannot apply 'activate' to agent in Running state"
The agent is already running — activate (Suspended → Running) and suspend (Running → Suspended) are the only two lifecycle commands, and each is only valid from one state. Check the agent's current state first:
hoziron-cli agent status <agent-id>
Registry unreachable
hoziron-cli catalog registry test
Check network connectivity and auth tokens.
CORS errors from dashboard
CORS must be configured if the dashboard connects directly:
[server.cors]
allowed_origins = ["https://dashboard.company.com"]
allow_credentials = true
Cannot use wildcard * with allow_credentials = true.
Route panic on startup (axum)
If you see a panic mentioning route syntax or path parameters: ensure path parameters use {param} syntax (axum 0.8), not :param.
Health check shows degraded
hoziron-cli health --json
Check which subsystem is degraded and see the specific troubleshooting page:
- Provider → providers.md
- Memory / kernel → recovery.md
- Latency → performance.md
Related: