Zie619/n8n-workflows · error · HTTPException
Error downloading workflow: {str(e)}
Error message
Error downloading workflow: {str(e)} What it means
The catch-all 500 for GET /api/workflows/{filename}/download. HTTPExceptions re-raise untouched, so reaching this handler means an unexpected exception while building or serving the FileResponse — e.g. the file disappearing between the scan and the response, or FileResponse failing to stat/open the path. The exception is printed server-side ('Error downloading workflow {filename}: ...') and wrapped into the 500 detail.
Source
Thrown at api_server.py:430
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:
raise
except Exception as e:
print(f"Error downloading workflow {filename}: {str(e)}")
raise HTTPException(
status_code=500, detail=f"Error downloading workflow: {str(e)}"
)
@app.get("/api/workflows/{filename}/diagram")
async def get_workflow_diagram(filename: str, request: Request):
"""Get Mermaid diagram code for workflow visualization."""
try:
# Security: Validate filename to prevent path traversal
if not validate_filename(filename):
print(f"Security: Blocked path traversal attempt for filename: {filename}")
raise HTTPException(status_code=400, detail="Invalid filename format")
# Security: Rate limiting
client_ip = request.client.host if request.client else "unknown"
if not check_rate_limit(client_ip):
raise HTTPException(
status_code=429, detail="Rate limit exceeded. Please try again later."View on GitHub (pinned to 94007c1445)
Solutions
- Read the detail text and the server console for the exact exception.
- Verify the file is readable by the server process user: ls -l workflows/<subdir>/<file> and sudo -u <user> cat <path>.
- Re-run the listing and retry the download with a filename known to currently exist.
- For recurring races, index/read files under a stable snapshot or pause cleanup during reindex.
Example fix
# before
return FileResponse(str(file_path), media_type='application/json', filename=filename)
# after (fail with a clear 410 when the file vanished mid-request)
if not file_path.is_file():
raise HTTPException(status_code=410, detail='Workflow file no longer available')
return FileResponse(str(file_path), media_type='application/json', filename=filename) Defensive patterns
Strategy: try-catch
Validate before calling
import requests
def file_served(base, name):
r = requests.head(f'{base}/api/workflows/{name}/download', timeout=5,
allow_redirects=True)
return r.status_code == 200 Try / catch
try:
save(client.get(f'/api/workflows/{name}/download'))
except HTTPError as e:
if e.response.status_code == 500:
log(e.response.json()['detail']) # contains the underlying OS error
revalidate_file_on_disk(name) Prevention
- Avoid deleting/renaming files while downloads are in flight.
- Keep read permissions stable for the server user.
- Retry once after confirming the file still exists in a fresh listing.
When it happens
Trigger: TOCTOU: file exists during the scan but is deleted before FileResponse opens it; permission error when the server process reads the file; FileResponse construction failing on a path that is actually a directory or a broken symlink that passed earlier checks.
Common situations: Concurrent cleanup scripts pruning workflows/; permissions changed while the server runs; exotic filesystems where stat succeeds but open fails.
Related errors
- Error loading workflow: {str(e)}
- Workflow file '{filename}' not found
- Error fetching stats: {str(e)}
- Workflow file '{filename}' not found on filesystem
- Error generating diagram: {str(e)}
AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15).
Data as JSON: /api/errors/2627940c409ce458.
Report an issue: GitHub.