{"record":{"id":"2906bd818f0419c9","repo":"zed-industries/zed","slug":"project-project-number-not-found","errorCode":null,"errorMessage":"project #{project_number} not found","messagePattern":"project #(.+?) not found","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"script/github-triage-queue-board.py","lineNumber":132,"sourceCode":"        for item in data[\"items\"]:\n            issues[item[\"node_id\"]] = item[\"number\"]\n        if len(data[\"items\"]) < 100 or page >= 10:\n            return issues\n        page += 1\n\n\ndef fetch_project_id(project_number):\n    data = github_graphql(\n        \"\"\"\n        query($owner: String!, $number: Int!) {\n          organization(login: $owner) { projectV2(number: $number) { id } }\n        }\n        \"\"\",\n        {\"owner\": REPO_OWNER, \"number\": project_number},\n    )\n    project = data[\"organization\"][\"projectV2\"]\n    if not project:\n        raise RuntimeError(f\"project #{project_number} not found\")\n    return project[\"id\"]\n\n\ndef project_items(project_id):\n    # Yields (item_id, content_id, number) for each issue on the project.\n    # content_id is the issue's global node id, which is the same value the REST\n    # search API returns as node_id, so it can be compared directly against the\n    # keys of eligible_issues().\n    cursor = None\n    while True:\n        data = github_graphql(\n            \"\"\"\n            query($project: ID!, $cursor: String) {\n              node(id: $project) {\n                ... on ProjectV2 {\n                  items(first: 100, after: $cursor) {\n                    pageInfo { hasNextPage endCursor }\n                    nodes { id content { ... on Issue { id number } } }","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/script/github-triage-queue-board.py#L114-L150","documentation":"fetch_project_id queries organization(login: REPO_OWNER).projectV2(number: project_number){ id } and GitHub answers with null — not a body error — when the project does not exist under that org or the token cannot see it; the script turns that null into this RuntimeError. Permission failure and wrong number are indistinguishable from here.","triggerScenarios":"PROJECT_NUMBER wrong or referring to a user-level project; token missing read:project scope; project private to another org; REPO_OWNER env wrong so the org lookup yields null projectV2.","commonSituations":"Board recreated with a new number; rotated token without project scope; workflow targeting the wrong org; fine-grained PAT without the org's projects selected.","solutions":["Verify the project number in the board URL and that it is an org project","Check token scopes/fine-grained permissions for project read on that org","Switch to user(login:){ projectV2 } if the project is user-owned","Print REPO_OWNER/PROJECT_NUMBER at startup to catch env mistakes"],"exampleFix":"// before\nproject = data[\"organization\"][\"projectV2\"]\nif not project:\n    raise RuntimeError(f\"project #{project_number} not found\")\n\n// after\nproject = data[\"organization\"][\"projectV2\"]\nif not project:\n    raise RuntimeError(\n        f\"project #{project_number} not found under {REPO_OWNER}; \"\n        \"check PROJECT_NUMBER, REPO_OWNER, and token project scopes\"\n    )","handlingStrategy":"validation","validationCode":"def project_number_is_plausible(number: int) -> bool:\n    return isinstance(number, int) and number > 0","typeGuard":"def projectv2_visible(data: dict) -> bool:\n    org = data.get(\"organization\") or {}\n    return bool(org.get(\"projectV2\"))","tryCatchPattern":"try:\n    project_id = fetch_project_id(project_number)\nexcept RuntimeError as exc:\n    if \"not found\" in str(exc):\n        raise SystemExit(\"Verify PROJECT_NUMBER, REPO_OWNER, and the token's read:project scope\")\n    raise","preventionTips":["Verify the project number from the board URL before configuring CI","Ensure the token can see org projects (read:project or fine-grained equivalent)","Alert when a board recreation changes the project number","Distinguish user projects from org projects in queries"],"tags":["github-projects","graphql","config","api-auth"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}