Postmortems/2026-05-07 n8n HA Credential Repair
As of: 2026-07-05 — migrated from `postmortems/2026-05-07-n8n-ha-credential-repair.md`
Postmortem: n8n Credential Failures & HA Workflow Repair
Date: 2026-05-07 Duration: ~6 hours of cascading failures (backup alerts since 2026-03-11 DB recovery) Severity: Medium — silent failures, no data loss, but monitoring blind spots Status: Resolved
Summary
After the March 2026 n8n SQLite DB recovery, 12 workflows were silently failing due to stale/placeholder credential IDs. Home Assistant workflows had additional issues: wrong credential format, missing entity IDs, and parallel-merge node connections that n8n can't execute correctly.
Root Causes (in order discovered)
1. Stale SSH credential IDs from DB recovery
The March 2026 DB recovery recreated credentials with new IDs, but workflow JSONs stored on disk still had old IDs. When workflows were re-imported they referenced credentials that no longer existed.
CREDENTIAL_ID— literal placeholder, never substitutedS2muq5nzJFa5ZydC— old SSH credential from pre-recovery DB
Current correct SSH credential ID: 2ugS1ibsZu1LQid8
2. Missing homeAssistantApi credential
The homeAssistantApi-type credential (different from httpHeaderAuth) was lost in the DB recovery. Eight workflows referenced ID 6CIwjyqyUwnvaezn which no longer existed.
3. Wrong credential host field format
n8n's homeAssistantApi credential uses separate host and port fields — the host is just the IP/hostname with no scheme, no port:
<syntaxhighlight lang="json"> {
"host": "192.168.0.140", "port": 8123, "accessToken": "...", "ssl": false
} </syntaxhighlight>
Wrong formats tried (and why they fail):
"host": "http://homeassistant.local:8123"→ Docker can't resolve.localmDNS names"host": "http://192.168.0.140:8123"→ node builds URL ashttp://http://192.168.0.140:8123→ DNS lookup of literal string"http"→EAI_AGAIN"host": "192.168.0.140:8123"→ node builds URL ashttp://192.168.0.140:8123:8123→ERR_INVALID_URL
How discovered: Read the actual compiled source at:
<syntaxhighlight lang="text">
docker exec n8n find /usr/local/lib/node_modules/n8n -path "*HomeAssistant/GenericFunctions.js"
</syntaxhighlight>
URL construction: ` ${ssl?'https':'http'}://${credentials.host}:${credentials.port}/api${resource} `
4. Missing entity IDs in HA node parameters
The entityId field was never saved in the original workflow JSONs exported from n8n. All HA state-read nodes had resource: "state" but no entityId.
Correct entity IDs used:
| Node purpose | Entity ID |
|---|---|
| Living room temp | sensor.ewelink_snzb_02p_temperature
|
| Beta sensor temp | sensor.temp_sensor_beta_temperature
|
| Closet/Charlie temp | sensor.temp_sensor_charlie_temperature
|
| Closet/Charlie humidity | sensor.temp_sensor_charlie_humidity
|
| Door sensor | binary_sensor.shellydw2_075374_door
|
| Weather forecast | weather.forecast_ronwood
|
| Phone next alarm | sensor.pixel_7_next_alarm
|
| Announce/TTS | media_player.home_assistant_voice_098a64
|
| HA notify | notify.home_assistant
|
5. Parallel-merge node connections
Workflows had multiple HA nodes connected in parallel (all from the trigger), all feeding into one downstream code node. n8n runs the downstream node as soon as the first upstream node finishes — so the code crashes with "Node X hasn't been executed" when it tries to read data from the still-running nodes.
Pattern causing the bug: <syntaxhighlight lang="text"> Trigger ──┬── Get Temp A ──┐
├── Get Temp B ──┼── Analyze ← runs on first finish, others not done
└── Get Temp C ──┘
</syntaxhighlight>
Fix — chain them sequentially: <syntaxhighlight lang="text"> Trigger → Get Temp A → Get Temp B → Get Temp C → Analyze </syntaxhighlight>
Each node passes its result downstream; the code node then accesses all previous nodes via $('Get Temp A').first() etc.
Affected workflows:
- Server Closet Monitor (Temp + Humidity)
- Home Temperature Alert (3 temp sensors)
- Morning Briefing (Weather + Energy Usage)
- Bedtime Routine (Door check + Weather)
Diagnostic Approach
How to find execution errors when the n8n API returns no detail: <syntaxhighlight lang="bash">
- execution_data table has the full run data
sudo sqlite3 /var/lib/docker/volumes/n8n-app_n8n_data/_data/database.sqlite \
"SELECT substr(ed.data,1,5000) FROM execution_entity ee JOIN execution_data ed ON ee.id = ed.executionId WHERE ee.id = <EXEC_ID>;"
- Then grep for: EAI_AGAIN, ENOTFOUND, ERR_INVALID_URL, "message", getaddrinfo
</syntaxhighlight>
How to find which credentials are broken: <syntaxhighlight lang="bash">
- Valid credential IDs in DB
sudo sqlite3 /var/lib/docker/volumes/n8n-app_n8n_data/_data/database.sqlite \
"SELECT id, name, type FROM credentials_entity ORDER BY name;"
- Scan all workflows for IDs not in that list
- (see the audit script logic used in this session)
</syntaxhighlight>
After any credential fix — n8n must be restarted: <syntaxhighlight lang="bash"> sudo -E sh -c 'cd /library/n8n-app && docker compose restart n8n' </syntaxhighlight> n8n caches credential validation state. Even after fixing a credential in the DB, workflows show "has issues" until restart.
Current Credential IDs (verified 2026-05-07)
| ID | Name | Type |
|---|---|---|
2ugS1ibsZu1LQid8
|
Stronghold SSH (mnw) | sshPrivateKey |
4RowxM0jrmYDnctK
|
Home Assistant API | homeAssistantApi |
w0gXpM8W793fahAY
|
ntfy Auth | httpHeaderAuth |
x5tv5aXs5N5nd2aK
|
Matrix Bot (Zordon) | httpHeaderAuth |
R9LGxXIhmWCRM5Cn
|
Home Assistant API (old httpHeaderAuth) | httpHeaderAuth |
5MCznsMsxjqOrlhJ
|
AudioBookshelf API | httpHeaderAuth |
XB0V2UwPdWkRJoWj
|
OpenAI Bearer | httpHeaderAuth |
NIQrbnzjhpNzBV1P
|
OpenAi account | openAiApi |
HA credential data format (correct):
- host:
192.168.0.140(IP only, no scheme, no port) - port:
8123 - ssl:
false - accessToken: from Vaultwarden → "Home Assistant Long-Lived Token"
Prevention
- After any n8n DB recovery: run the credential audit script before assuming workflows work. Check every active workflow's credential IDs against
credentials_entity. - Export workflow JSONs immediately after any credential re-creation so the repo stays in sync.
- Never use
homeassistant.localin n8n — Docker containers can't resolve mDNS. Always use192.168.0.140. - n8n parallel-merge pattern is broken — if multiple nodes need to read data before a code node, chain them sequentially, not in parallel.
- Test workflows after changes — check n8n execution history within 30 min of any credential/workflow change.