{"record":{"id":"cbd5b3219eaf8159","repo":"theonedev/onedev","slug":"no-package-write-permission-for-project","errorCode":null,"errorMessage":"No package write permission for project: ","messagePattern":"No package write permission for project: ","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-plugin/server-plugin-pack-npm/src/main/java/io/onedev/server/plugin/pack/npm/NpmPackHandler.java","lineNumber":583,"sourceCode":"\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic String getApiKey(HttpServletRequest request) {\n\t\tvar authzHeader = request.getHeader(HttpHeaders.AUTHORIZATION);\n\t\tif (authzHeader != null&& authzHeader.toLowerCase().startsWith(\"bearer \")) \n\t\t\treturn StringUtils.substringAfter(authzHeader, \" \");\n\t\telse\n\t\t\treturn null;\n\t}\n\n\tprivate Project checkProject(Long projectId, boolean needsToWrite) {\n\t\tvar project = projectService.load(projectId);\n\t\tif (!project.isPackManagement())\n\t\t\tthrow new ClientException(SC_NOT_ACCEPTABLE, \"Package management not enabled for project '\" + project.getPath() + \"'\");\n\t\telse if (needsToWrite && !SecurityUtils.canWritePack(project))\n\t\t\tthrow new UnauthorizedException(\"No package write permission for project: \" + project.getPath());\n\t\telse if (!needsToWrite && !SecurityUtils.canReadPack(project))\n\t\t\tthrow new UnauthorizedException(\"No package read permission for project: \" + project.getPath());\n\t\treturn project;\n\t}\n\t\n\t@Override\n\tpublic List<String> normalize(List<String> pathSegments) {\n\t\treturn pathSegments;\n\t}\n\n}\n","sourceCodeStart":565,"sourceCodeEnd":595,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-pack-npm/src/main/java/io/onedev/server/plugin/pack/npm/NpmPackHandler.java#L565-L595","documentation":"Thrown by checkProject when a write operation (npm publish or unpublish) is attempted by a user who lacks pack write permission on the project. It raises UnauthorizedException, which OneDev surfaces as HTTP 401 to the npm client.","triggerScenarios":"PUT publish or DELETE unpublish where SecurityUtils.canWritePack(project) is false for the authenticated user — typically the account used in .npmrc is a job token or read-only user.","commonSituations":"Using a CI job secret token that only has read access; missing or expired access token in .npmrc (_authToken); user not added to the project with sufficient role; anonymous access configured instead of a credential.","solutions":["Set a valid access token with package write permission in .npmrc: //onedev.example.com/:_authToken=<token>.","Grant the user/job's role Pack Write (or higher) on the project in OneDev's authorization settings.","Verify the Bearer token actually maps to an account with write access (test with a metadata GET first).","Regenerate an expired token from User Profile -> Access Tokens and update .npmrc."],"exampleFix":"// before (.npmrc)\n//onedev.example.com/:_authToken=<readonly-token>\n// after\n//onedev.example.com/:_authToken=<token-of-user-with-pack-write>","handlingStrategy":"try-catch","validationCode":"// Pre-check write access before publishing\nconst resp = await fetch(`${registryUrl}/${pkgName}`, { headers: { Authorization: `Bearer ${token}` } });\nif (!resp.ok) throw new Error(`Registry auth failed: ${resp.status} — check token and Pack Write permission`);","typeGuard":null,"tryCatchPattern":"try {\n  await npmPublish();\n} catch (e) {\n  if (String(e).includes('No package write permission') || e.code === 'E401') {\n    console.error('Publish unauthorized: use a token whose user has Pack Write on the project');\n  } else throw e;\n}","preventionTips":["Provision CI tokens with Pack Write for publish pipelines.","Rotate tokens before expiry and update .npmrc.","Test publish access with a dry-run before releases."],"tags":["npm","http-401","authorization"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}