Zie619/n8n-workflows · error · HTTPException

Workflow file '{filename}' not found

Error message

Workflow file '{filename}' not found

What it means

A 404 from GET /api/workflows/{filename}/download when no candidate file is found: the handler scans only immediate subdirectories of workflows/ (subdir / filename, kept only if target.exists() and target.is_file() and resolve() stays inside workflows_path). An empty json_files list raises this error, with a server-side log line 'File {filename} not found in workflows directory'.

Source

Thrown at api_server.py:408

        json_files = []
        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 (defense in depth)
                    try:
                        target_file.resolve().relative_to(workflows_path)
                        json_files.append(target_file)
                    except ValueError:
                        # File is outside workflows directory
                        print(
                            f"Security: Blocked access to file outside workflows: {target_file}"
                        )
                        continue

        if not json_files:
            print(f"File {filename} not found in workflows directory")
            raise HTTPException(
                status_code=404, detail=f"Workflow file '{filename}' not found"
            )

        file_path = json_files[0]

        # Final security check: Ensure file is within workflows directory
        try:
            file_path.resolve().relative_to(workflows_path)
        except ValueError:
            print(
                f"Security: Blocked final attempt to access file outside workflows: {file_path}"
            )
            raise HTTPException(status_code=403, detail="Access denied")

        return FileResponse(
            str(file_path), media_type="application/json", filename=filename
        )
    except HTTPException:

View on GitHub (pinned to 94007c1445)

Solutions

  1. Verify the file exists at workflows/<subdir>/<filename> and re-run the search listing to get a fresh filename.
  2. Reindex after filesystem changes so listings stop advertising missing files.
  3. Keep all workflow JSONs exactly one subdirectory below workflows/.
  4. Check the server log for 'Blocked access to file outside workflows' — that indicates a symlink/containment issue rather than absence.

Example fix

# before
json_files.append(target_file) only from subdirectories

# after (accept top-level files too)
candidates = [p for p in [subdir / filename for subdir in workflows_path.iterdir() if subdir.is_dir()] + [workflows_path / filename] if p.exists() and p.is_file()]
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def downloadable(workflows_dir, filename):
    root = Path(workflows_dir).resolve()
    for sub in root.iterdir():
        if sub.is_dir():
            cand = sub / filename
            if cand.is_file():
                try:
                    cand.resolve().relative_to(root)
                    return True
                except ValueError:
                    pass
    return False

Try / catch

try:
    r = client.get(f'/api/workflows/{name}/download')
    r.raise_for_status()
except HTTPError as e:
    if e.response.status_code == 404:
        refresh_listing_and_remove(name)  # stop offering stale downloads

Prevention

When it happens

Trigger: Downloading a file that was deleted/moved after it appeared in a listing; a file at workflows/ top level (never scanned); a filename whose on-disk case differs; a file reachable only via a symlink resolving outside workflows/ (dropped by the containment check).

Common situations: Stale browser tab listing from before files were reorganized; renaming files outside the app; deeper nesting than the one-subdirectory layout.

Related errors


AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15). Data as JSON: /api/errors/030ccf80413c7c24. Report an issue: GitHub.