{"record":{"id":"a57d22f237e558d5","repo":"makeplane/plane","slug":"project-id-is-required","errorCode":null,"errorMessage":"Project ID is required","messagePattern":"Project ID is required","errorType":"exception","errorClass":"CommandError","httpStatus":null,"severity":"error","filePath":"apps/api/plane/db/management/commands/create_project_member.py","lineNumber":31,"sourceCode":"    ProjectMember,\n    Project,\n    ProjectUserProperty,\n)\n\n\nclass Command(BaseCommand):\n    help = \"Add a member to a project. If present in the workspace\"\n\n    def add_arguments(self, parser):\n        # Positional argument\n        parser.add_argument(\"--project_id\", type=str, nargs=\"?\", help=\"Project ID\")\n        parser.add_argument(\"--user_email\", type=str, nargs=\"?\", help=\"User Email\")\n        parser.add_argument(\"--role\", type=int, nargs=\"?\", help=\"Role of the user in the project\")\n\n    def handle(self, *args: Any, **options: Any):\n        try:\n            if not options[\"project_id\"]:\n                raise CommandError(\"Project ID is required\")\n            if not options[\"user_email\"]:\n                raise CommandError(\"User Email is required\")\n\n            project_id = options[\"project_id\"]\n            user_email = options[\"user_email\"]\n            role = options.get(\"role\", 20)\n\n            print(f\"Role: {role}\")\n\n            user = User.objects.filter(email=user_email).first()\n            if not user:\n                raise CommandError(\"User not found\")\n\n            # Check if the project exists\n            project = Project.objects.filter(pk=project_id).first()\n            if not project:\n                raise CommandError(\"Project not found\")\n","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/makeplane/plane/blob/1c8a60f858d8472aa56e29994ec1c7926da2c6ce/apps/api/plane/db/management/commands/create_project_member.py#L13-L49","documentation":"Raised by `create_project_member` when `--project_id` is not supplied or is falsy (line 30). Unlike positional args, `--project_id` is declared with `nargs=\"?\"` (line 24), so argparse does NOT enforce its presence and the value defaults to `None`, making this check genuinely reachable. Note the command's `try/except CommandError` (lines 70-71) swallows it to an ERROR stdout line and returns 0.","triggerScenarios":"Running `python manage.py create_project_member --user_email x@example.com` without `--project_id`, or passing `--project_id ''`.","commonSituations":"Forgot the flag; copy-paste from docs that omitted the flag; script that conditionally omits the argument.","solutions":["Supply the UUID: `python manage.py create_project_member --project_id <uuid> --user_email <email>`","Find the project id: `python manage.py shell -c \"from plane.db.models import Project; print(Project.objects.values_list('id','name'))\"`","In wrapper scripts, guard with `if not project_id: sys.exit('project_id required')` before invoking."],"exampleFix":"# before\npython manage.py create_project_member --user_email x@example.com\n# after\npython manage.py create_project_member --project_id 12345678-1234-... --user_email x@example.com","handlingStrategy":"validation","validationCode":"import sys\nproject_id = None  # from your script\nif not project_id:\n    sys.exit('--project_id is required')","typeGuard":"def has_project_id(value) -> bool:\n    return isinstance(value, str) and len(value) > 0","tryCatchPattern":"# create_project_member swallows CommandError (returns 0), so the shell won't see it.\n# Validate args before invoking instead.","preventionTips":["Always pass --project_id (nargs='?' means argparse won't enforce it).","Resolve the project UUID from the shell before running.","Validate in wrapper scripts before invoking."],"tags":["django","management-command","validation","cli-args","plane"],"backgroundTag":null,"analyzedSha":"1c8a60f858d8472aa56e29994ec1c7926da2c6ce","analyzedAt":"2026-08-12T14:44:31.636Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}