fix(workflows): resolve the kokoro dependency to the tts service - #2495
Open
Hoang130203 wants to merge 1 commit into
Open
fix(workflows): resolve the kokoro dependency to the tts service#2495Hoang130203 wants to merge 1 commit into
Hoang130203 wants to merge 1 commit into
Conversation
check_workflow_dependencies() reports a dependency it cannot resolve as
satisfied, without probing anything:
resolved = _DEP_ALIASES.get(dep, dep)
if resolved in health_cache: ...
elif resolved in SERVICES: ...probe it...
else:
results[dep] = True # unknown name -> "ready"
config/n8n/catalog.json gives voice-to-voice the dependencies
["whisper", "llama-server", "kokoro"]. There is no `kokoro` service —
Kokoro is the model the `tts` service serves, and the service id is
`tts`. So the name falls through the else branch and the Workflows page
shows voice-to-voice with its dependencies met whether or not TTS is
installed or running. The user imports it and it fails at the speech
node.
_DEP_ALIASES already exists for exactly this ("ollama" -> "llama-server").
Adds "kokoro" -> "tts" so the tts health probe actually runs.
Also adds tests/test-n8n-catalog-contract.py, which reads _DEP_ALIASES
out of the router and asserts every catalog dependency resolves to a
directory under extensions/services/ — plus that every entry names a
file that exists, sits in a declared category, has unique ids, that no
workflow file is missing from the catalog, and that every workflow's
connections reference nodes that exist. Wired into `make test` and the
Linux CI job.
This was referenced Aug 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
check_workflow_dependencies()reports a dependency it cannot resolve assatisfied, without probing anything:
config/n8n/catalog.jsongivesvoice-to-voicethe dependencies["whisper", "llama-server", "kokoro"]. There is nokokoroservice —Kokoro is the model the
ttsservice serves (ghcr.io/remsky/kokoro-fastapi-cpu),and the service id is
tts:So
kokoromisses both the alias map andSERVICES, falls through theelse,and the Workflows page shows
voice-to-voicewith its dependencies met whetheror not TTS is installed or running.
all_deps_metis computed from exactlythese values:
The user sees a ready card, imports the workflow, and it fails at the speech
node. Of the three declared dependencies, whisper and llama-server are checked
honestly; the one that is silently assumed is the one most likely to be absent,
since
ttsis an optional extension.Fix
_DEP_ALIASESexists for precisely this case —"ollama"is already mapped to"llama-server". Add"kokoro"→"tts"so the tts health probe actuallyruns.
I chose the alias over renaming the dependency in the catalog because
kokorois the name a user recognises from the workflow's description, and the alias
map is where the codebase already handles this mismatch.
I deliberately did not change the fail-open
elsebranch to fail closed.It is load-bearing for dependencies that are not ODS services at all, and
flipping it is a behaviour change on the dashboard that deserves its own
discussion. The contract test below makes the typo case impossible instead.
Test
Two additions to
tests/test_workflows.py: one assertingkokoroandollamaboth resolve to a probed service, one pinning the fail-open behaviour for a
genuinely unknown name so a future change to it is deliberate.
Plus
tests/test-n8n-catalog-contract.py, which reads_DEP_ALIASESback outof the router source (no FastAPI import needed) and asserts, for the whole
catalog:
extensions/services/;fields and unique ids;
connectionsreference nodes that exist.229 assertions today. Wired into
make testand the Linux CI job.AI Assistance
AI assisted with tracing the fail-open branch, drafting the contract test, and
wording this description. I read the full diff, confirmed there is no
kokoroservice directory and that
ttsis the id, and ran both suites againstorigin/mainand the patch.Release Lane
release/2.6.xmainStable hotfix reason:
Changed Surface
(One entry in a lookup table in
routers/workflows.py, plus tests. CI configand the Makefile test target are also touched.)
Risk And Validation
git diff --checkrelease/2.6.xCommands/results:
Operational Change Check
check_workflow_dependencies()runs on the dashboard-api/api/workflowsread path. The change makes one more dependency name route to a real health
probe. The only behaviour change:
voice-to-voicenow shows its TTSdependency as unmet when the tts service is down or not installed, instead of
always showing it met. No write path, no schema change, no other workflow
affected.
Notes For Reviewers
The bigger thing I found while writing the contract test, and am not fixing
here: all 18 workflows in
config/n8n/are placeholders. Every one is amanualTriggerplus astickyNotereading "This is a template workflow…Customize the nodes below to match your setup", with
"connections": {}—nothing is wired to anything:
Meanwhile the catalog advertises them with real descriptions and
"setupTime": "2 minutes".tests/integration-test.shpasses them because itonly checks that the JSON parses and has a
nodeskey.That is a content gap rather than a defect in this code path, and filling it is
ods/CONTRIBUTING.md's "Workflow templates — pre-built n8n workflows thatsolve actual problems people have". I am working through implementing them as
separate PRs, starting with the llama-server-only ones. The connection-graph
assertions in this contract test are there to catch a half-wired workflow when
those land.
Tell me if you would rather the catalog mark unimplemented entries explicitly
(e.g. a
"status": "template"field the dashboard can badge) — that is asmaller change than implementing all 18 and would stop the page over-promising
in the meantime.