{"record":{"id":"951819200317cde9","repo":"agentscope-ai/agentscope","slug":"requested-path-is-a-directory-not-a-file","errorCode":null,"errorMessage":"Requested path is a directory, not a file.","messagePattern":"Requested path is a directory, not a file\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"src/agentscope/app/_router/_workspace.py","lineNumber":590,"sourceCode":"        )\n\n    workspace = await workspace_service.resolve(\n        user_id,\n        agent_id,\n        session_id,\n    )\n    backend = workspace.get_backend()\n    target = backend.abspath(path, cwd=workspace.workdir)\n    basename = backend.basename(target) or \"download\"\n\n    entry = await backend.stat(target)\n    if entry is None:\n        raise HTTPException(\n            status_code=status.HTTP_404_NOT_FOUND,\n            detail=\"File not found.\",\n        )\n    if entry.is_dir:\n        raise HTTPException(\n            status_code=status.HTTP_400_BAD_REQUEST,\n            detail=\"Requested path is a directory, not a file.\",\n        )\n\n    headers: dict[str, str] = {}\n    # Lets the browser show real download progress instead of a\n    # spinner of unknown length; omitted when the backend cannot stat.\n    if entry.size_bytes is not None:\n        headers[\"Content-Length\"] = str(entry.size_bytes)\n    if download:\n        headers[\n            \"Content-Disposition\"\n        ] = f\"attachment; filename*=UTF-8''{quote(basename)}\"\n\n    return StreamingResponse(\n        backend.read_stream(target),\n        media_type=(\n            mimetypes.guess_type(basename)[0] or \"application/octet-stream\"","sourceCodeStart":572,"sourceCodeEnd":608,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/app/_router/_workspace.py#L572-L608","documentation":"Raised by read_workspace_file when the requested workspace path exists but is a directory rather than a regular file. The router checks the entry's is_dir flag after confirming existence and rejects directory paths because a file download/read endpoint cannot stream a directory. It is an HTTP 400 because the request is syntactically valid but semantically wrong for this endpoint.","triggerScenarios":"Calling GET on the workspace file-read endpoint (e.g. /workspace/file?path=docs or any path ending in /) where the path resolves to a folder inside the workspace. Also happens when a client builds a path from a listing and forgets to append a filename.","commonSituations":"UI file browser passing the currently selected folder instead of a file to the download button; hardcoded example paths like 'README' that are actually directories; off-by-one in path construction appending an empty filename segment.","solutions":["Verify the path points to a file (e.g. via the workspace listing endpoint) before calling read_workspace_file","If you meant to fetch a file inside the folder, append the filename: 'docs/' -> 'docs/README.md'","If you need directory contents, call the list/directory endpoint instead of the file-read endpoint","Check the entry metadata (is_dir flag) returned by the listing API and disable download for directories in your UI"],"exampleFix":"// before\nawait client.read_workspace_file(path=\"docs/\")\n// after\nentries = await client.list_workspace(path=\"docs/\")\nfile_entry = next(e for e in entries if not e.is_dir)\nawait client.read_workspace_file(path=f\"docs/{file_entry.name}\")","handlingStrategy":"validation","validationCode":"listing = await client.list_workspace(path=parent_dir)\nentry = next((e for e in listing if e.name == name), None)\nif entry is None or entry.is_dir:\n    raise ValueError(f\"{path} is not a readable workspace file\")\ncontent = await client.read_workspace_file(path=path)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always derive file paths from a directory listing rather than string concatenation","Disable download buttons in the UI for entries with is_dir true"],"tags":["workspace","file-system","http-400","path-validation"],"backgroundTag":"path-is-directory","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}