{"record":{"id":"34b7c5079125e54c","repo":"langchain-ai/deepagents","slug":"workspace-field-is-not-a-directory-value","errorCode":null,"errorMessage":"workspace.{field} is not a directory: {value}","messagePattern":"workspace\\.(.+?) is not a directory: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/workspace.py","lineNumber":89,"sourceCode":"    if not isinstance(value, str) or not value or len(value) > _MAX_PATH_LENGTH:\n        msg = f\"workspace.{field} must be a non-empty absolute path\"\n        raise ValueError(msg)\n    candidate = Path(value)\n    if not candidate.is_absolute() or \"..\" in PurePath(value).parts:\n        msg = f\"workspace.{field} must be an absolute path without traversal\"\n        raise ValueError(msg)\n    if os.name != \"nt\":\n        from deepagents.backends.utils import validate_path\n\n        validate_path(value)\n    try:\n        resolved = candidate.resolve(strict=True)\n    except (OSError, RuntimeError) as exc:\n        msg = f\"workspace.{field} is unavailable: {value}\"\n        raise ValueError(msg) from exc\n    if not resolved.is_dir():\n        msg = f\"workspace.{field} is not a directory: {value}\"\n        raise ValueError(msg)\n    if os.name != \"nt\":\n        from deepagents.backends.utils import validate_path\n\n        validate_path(str(resolved))\n    return resolved\n\n\ndef canonical_workspace_config(value: object | None) -> tuple[str, str]:\n    \"\"\"Return bounded canonical JSON and its SHA-256 fingerprint.\n\n    Raises:\n        TypeError: If the configuration is not an object.\n        ValueError: If it cannot be serialized or exceeds the size limit.\n    \"\"\"\n    if value is None:\n        value = {}\n    if not isinstance(value, dict):\n        msg = \"workspace_config must be an object\"","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/workspace.py#L71-L107","documentation":"Raised when the workspace path exists and resolves successfully but is not a directory (e.g. it is a file, socket, or other non-directory entry). _canonical_directory checks resolved.is_dir() after strict resolution so workspaces always point at real directories.","triggerScenarios":"Calling resolve_workspace with workspace.{field} set to a regular file path (e.g. /home/me/config.json) or any non-directory filesystem object.","commonSituations":"Config pointing at a file instead of its parent directory (copy-paste of a file path); a directory replaced by a file during refactoring; tools that wrote a file where a directory was expected.","solutions":["Point the workspace field at the directory, not a file: use the parent directory of the file.","Create the intended directory if it does not exist.","Verify with os.path.isdir / Path.is_dir before calling."],"exampleFix":"// before\nresolve_workspace(workspace={'dir': '/home/me/project/notes.md'})\n// after\nresolve_workspace(workspace={'dir': '/home/me/project'})","handlingStrategy":"validation","validationCode":"from pathlib import Path\np = Path(cfg['dir']).resolve(strict=True)\nif not p.is_dir():\n    raise NotADirectoryError(f'{p} is not a directory')","typeGuard":"def is_directory(value: str) -> bool:\n    return Path(value).is_dir()","tryCatchPattern":"try:\n    ws = resolve_workspace(workspace={'dir': cfg['dir']})\nexcept ValueError as e:\n    logger.error('workspace must be a directory: %s', e)","preventionTips":["Verify paths with Path.is_dir() before assigning to workspace fields","If a file path is given, use its .parent directory instead","Avoid replacing directories with same-named files in refactors"],"tags":["filesystem","path","workspace","validation"],"backgroundTag":"path-not-found","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}