{"record":{"id":"1587d78048530bc4","repo":"pulumi/pulumi","slug":"failed-to-find-project-settings-file-in-workdir-1587d7","errorCode":null,"errorMessage":"failed to find project settings file in workdir: {work_dir}","messagePattern":"failed to find project settings file in workdir: (.+?)","errorType":"exception","errorClass":"FileNotFoundError","httpStatus":null,"severity":"error","filePath":"sdk/python/lib/pulumi/automation/_local_workspace.py","lineNumber":1081,"sourceCode":"    return ProjectSettings(name=project_name, runtime=\"python\", main=os.getcwd())\n\n\ndef get_stack_settings_name(name: str) -> str:\n    parts = name.split(\"/\")\n    if len(parts) < 1:\n        return name\n    return parts[-1]\n\n\ndef _load_project_settings(work_dir: str) -> ProjectSettings:\n    for ext in _setting_extensions:\n        project_path = os.path.join(work_dir, f\"Pulumi{ext}\")\n        if not os.path.exists(project_path):\n            continue\n        with open(project_path, encoding=\"utf-8\") as file:\n            settings = json.load(file) if ext == \".json\" else yaml.safe_load(file)\n            return ProjectSettings.from_dict(settings)\n    raise FileNotFoundError(\n        f\"failed to find project settings file in workdir: {work_dir}\"\n    )\n","sourceCodeStart":1063,"sourceCodeEnd":1084,"githubUrl":"https://github.com/pulumi/pulumi/blob/793f7b2e160db4321fb7fb6b0607461e01cb251e/sdk/python/lib/pulumi/automation/_local_workspace.py#L1063-L1084","documentation":"LocalWorkspace.get_project_settings iterates over the known project settings filenames (Pulumi.yaml, Pulumi.json, Pulumi.yml) in the given work directory and loads the first one it finds. If none of these files exists, it raises FileNotFoundError. This guards downstream operations that require project metadata (project name, runtime, etc.) which would otherwise fail with more confusing errors.","triggerScenarios":"Calling LocalWorkspace methods that read project settings (e.g. get_project_settings(), or operations that lazily load settings such as stack name parsing) against a directory that contains no Pulumi.yaml/Pulumi.yml/Pulumi.json file.","commonSituations":"Passing the wrong work_dir to LocalWorkspace (parent directory instead of the project root); running from a temp/scratch directory; project settings file renamed or deleted; Pulumi.yaml stored with an unusual extension.","solutions":["Point LocalWorkspace work_dir at the directory that actually contains Pulumi.yaml (or Pulumi.json/.yml)","Create the project settings file with `pulumi new` or by writing a minimal Pulumi.yaml","Check os.path.exists for the settings file before constructing the workspace","Verify the file uses a supported extension: .yaml, .yml, or .json"],"exampleFix":"// before\nws = LocalWorkspace(work_dir=\"/tmp/scratch\")\nsettings = ws.get_project_settings()\n// after\nws = LocalWorkspace(work_dir=\"/path/to/project\")  # contains Pulumi.yaml\nsettings = ws.get_project_settings()","handlingStrategy":"validation","validationCode":"import os\nfor ext in (\".yaml\", \".yml\", \".json\"):\n    if os.path.exists(os.path.join(work_dir, f\"Pulumi{ext}\")):\n        break\nelse:\n    raise FileNotFoundError(f\"no Pulumi project settings in {work_dir}\")","typeGuard":"def has_project_settings(work_dir: str) -> bool:\n    return any(os.path.exists(os.path.join(work_dir, f\"Pulumi{ext}\"))\n               for ext in (\".yaml\", \".yml\", \".json\"))","tryCatchPattern":"try:\n    settings = ws.get_project_settings()\nexcept FileNotFoundError:\n    settings = None  # or prompt user to run `pulumi new`","preventionTips":["Always point work_dir at the directory containing Pulumi.yaml","Check for the settings file before constructing LocalWorkspace","Keep the settings file out of .gitignore","Standardize on Pulumi.yaml across projects to avoid extension confusion"],"tags":["python","automation-api","file-not-found","workspace"],"backgroundTag":"missing-project-settings-file","analyzedSha":"793f7b2e160db4321fb7fb6b0607461e01cb251e","analyzedAt":"2026-08-31T09:36:43.099Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}