Zie619/n8n-workflows · error · HTTPException
Workflow file '{filename}' not found on filesystem
Error message
Workflow file '{filename}' not found on filesystem What it means
A 404 from GET /api/workflows/{filename} raised after the metadata was found in the database but no matching file was located on disk. The handler iterates only immediate subdirectories of workflows/ (subdir / filename) and additionally requires the resolved path to stay inside workflows_path; if no subdirectory contains the file, matching_file stays None and this error is raised (server logs 'Warning: File {filename} not found in workflows directory').
Source
Thrown at api_server.py:355
matching_file = None
for subdir in workflows_path.iterdir():
if subdir.is_dir():
target_file = subdir / filename
if target_file.exists() and target_file.is_file():
# Verify the file is actually within workflows directory
try:
target_file.resolve().relative_to(workflows_path)
matching_file = target_file
break
except ValueError:
print(
f"Security: Blocked access to file outside workflows: {target_file}"
)
continue
if not matching_file:
print(f"Warning: File {filename} not found in workflows directory")
raise HTTPException(
status_code=404,
detail=f"Workflow file '{filename}' not found on filesystem",
)
with open(matching_file, "r", encoding="utf-8") as f:
raw_json = json.load(f)
return {"metadata": workflow_meta, "raw_json": raw_json}
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error loading workflow: {str(e)}")
@app.get("/api/workflows/{filename}/download")
async def download_workflow(filename: str, request: Request):
"""Download workflow JSON file with security validation."""
try:View on GitHub (pinned to 94007c1445)
Solutions
- Confirm the file still exists under a subdirectory of workflows/ (e.g. workflows/<category>/<file>.json) and restore it if moved.
- Reindex after any filesystem change so the DB and disk agree.
- If you need top-level or nested-deeper files, adjust the search loop in api_server.py to also check workflows_path / filename or recurse.
- Avoid symlinks pointing outside workflows/ — they fail the resolve().relative_to(workflows_path) containment check by design.
Example fix
# before
for subdir in workflows_path.iterdir():
if subdir.is_dir():
target_file = subdir / filename
# after (also accept top-level files)
for subdir in workflows_path.iterdir():
target = subdir / filename if subdir.is_dir() else None
if target and target.exists() and target.is_file():
matching_file = target
break
if not matching_file:
top = workflows_path / filename
if top.exists() and top.is_file():
matching_file = top Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def file_findable(workflows_dir, filename):
root = Path(workflows_dir).resolve()
return any(
(sub / filename).is_file() and str((sub / filename).resolve()).startswith(str(root))
for sub in root.iterdir() if sub.is_dir()
) Try / catch
try:
data = client.get(f'/api/workflows/{name}').json()
except HTTPError as e:
if e.response.status_code == 404:
# index says yes, disk says no: check layout, then reindex
assert file_findable('workflows', name), 'file missing or misplaced' Prevention
- Keep every workflow exactly one subdirectory below workflows/.
- Reindex after moving, renaming, or deleting files.
- Avoid symlinks pointing outside workflows/.
When it happens
Trigger: The DB is stale: it indexes a file that was deleted, moved, or renamed on disk. Also triggered by files placed directly at workflows/ top level (only subdirectories are scanned, one level deep) or by symlinked subdirectories whose targets resolve outside workflows_path.
Common situations: Files deleted or renamed after indexing; a manual DB edit; directory restructuring that flattened or deepened the layout beyond one subdirectory level.
Related errors
- Workflow file '{filename}' not found
- Workflow not found in database
- Error loading workflow: {str(e)}
- Error downloading workflow: {str(e)}
- Workflow not found
AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15).
Data as JSON: /api/errors/48e058b5e90eb30c.
Report an issue: GitHub.