langflow-ai/langflow · warning · HTTPException
Folder must be one of: {', '.join(sorted(allowed_folders))}
Error message
Folder must be one of: {', '.join(sorted(allowed_folders))} What it means
HTTP 400 from GET /files/profile_pictures/{folder_name}/{file_name} when folder_name is not in the allow-list computed by _get_allowed_profile_picture_folders(settings_service) — the set of folder names derived from the config dir's profile_pictures/ tree plus the package's bundled profile_pictures directories. The message enumerates the sorted allowed names so the caller can self-correct.
Source
Thrown at src/backend/base/langflow/api/v1/files.py:210
raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/profile_pictures/{folder_name}/{file_name}")
async def download_profile_picture(
folder_name: ValidatedFolderName,
file_name: ValidatedFileName,
settings_service: Annotated[SettingsService, Depends(get_settings_service)],
):
"""Download profile picture from local filesystem.
Profile pictures are first looked up in config_dir/profile_pictures/,
then fallback to the package's bundled profile_pictures directory.
"""
try:
# Only allow specific folder names (dynamic from config + package)
allowed_folders = _get_allowed_profile_picture_folders(settings_service)
if folder_name not in allowed_folders:
raise HTTPException(status_code=400, detail=f"Folder must be one of: {', '.join(sorted(allowed_folders))}")
# SECURITY: Extract only the final path component to prevent path traversal.
# This is defense-in-depth on top of ValidatedFileName/ValidatedFolderName.
safe_folder = Path(folder_name).name
safe_file = Path(file_name).name
extension = safe_file.split(".")[-1]
config_dir = settings_service.settings.config_dir
# SECURITY: use os.path.realpath + startswith — the sanitiser pattern
# recognised by CodeQL's py/path-injection analysis. realpath canonicalises
# the path and resolves symlinks, so the subsequent startswith check is
# robust against both traversal sequences and symlink-based escapes.
# os.path.join is deliberate here (PTH118) to match CodeQL's sanitiser model.
allowed_base = os.path.realpath(os.path.join(str(config_dir), "profile_pictures")) # noqa: PTH118
candidate = os.path.realpath(os.path.join(allowed_base, safe_folder, safe_file)) # noqa: PTH118
if candidate != allowed_base and not candidate.startswith(allowed_base + os.sep):
raise HTTPException(status_code=404, detail="Profile picture not found")View on GitHub (pinned to 976ec789d2)
Solutions
- Use one of the folder names listed verbatim in the error detail
- Create the folder under <config_dir>/profile_pictures/ with at least one image so it enters the allow-list
- Check case-sensitivity — the comparison is exact
Example fix
# before GET /files/profile_pictures/Avatars/avatar_1.png # 400 # after mkdir -p ~/.langflow/profile_pictures/Avatars # add image cp avatar_1.png ~/.langflow/profile_pictures/Avatars/ GET /files/profile_pictures/Avatars/avatar_1.png
Defensive patterns
Strategy: validation
Validate before calling
ALLOWED_FOLDERS = {"defaults", "custom"} # sync with server config
def folder_allowed(folder_name: str, allowed: set[str]) -> bool:
return folder_name in allowed Type guard
function isAllowedProfileFolder(folder: string, allowed: string[]): boolean {
return allowed.includes(folder);
} Try / catch
try:
client.get(f"/files/profile_pictures/{folder}/{name}").raise_for_status()
except HTTPError as e:
if e.response.status_code == 400:
allowed = parse_allowed_folders(e.response.text)
client.get(f"/files/profile_pictures/{pick(allowed)}/{name}") Prevention
- Fetch the folder list from the error/config once and cache it client-side
- Provision custom picture folders on every deployment before referencing them
- Match folder names exactly — the check is case-sensitive
When it happens
Trigger: GET /files/profile_pictures/{unknown}/{file} with a folder not present under config_dir/profile_pictures/ or the bundled set; typos in folder names ('spaces' vs 'space', case sensitivity); requesting a folder that exists on one deployment but not another.
Common situations: Custom profile picture sets added to a different instance; renaming theme folders; frontend hardcoding a folder name that the deployment never provisioned.
Related errors
- Invalid path
- Failed to install MCP
- Provider '{provider}' is not configured. Available providers
- Could not extract class name from code
- Inputs and outputs have overlapping names: {overlap}
AI-assisted analysis of langflow-ai/langflow@976ec789d2 (2026-08-14).
Data as JSON: /api/errors/5638729a2d87c0ad.
Report an issue: GitHub.