{"record":{"id":"393658676620d37b","repo":"theonedev/onedev","slug":"unauthorized-393658","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/ArtifactResource.java","lineNumber":100,"sourceCode":"\t\tvar projectId = build.getProject().getId();\n\t\tvar buildNumber = build.getNumber();\n\t\tvar normalizedPath = normalizeArtifactPath(artifactPath);\n\t\treturn os -> {\n\t\t\tbuildService.downloadArtifact(projectId, buildNumber, normalizedPath, os);\n\t\t};\n\t}\n\n\t@Api(order=300, description = \"Upload artifact to specified path\")\n\t@Path(\"/{buildId}/{artifactPath:(.*)}\")\n\t@POST\n\t@Consumes(APPLICATION_OCTET_STREAM)\n\tpublic Response uploadArtifact(\n\t\t\t@PathParam(\"buildId\") Long buildId, \n\t\t\t@PathParam(\"artifactPath\") @Api(example = \"path/to/file\") String artifactPath, \n\t\t\tInputStream input) {\n\t\tBuild build = buildService.load(buildId);\n\t\tif (!SecurityUtils.canManageBuild(build))\n\t\t\tthrow new UnauthorizedException();\n\n\t\tbuildService.uploadArtifact(build.getProject().getId(), build.getNumber(),\n\t\t\t\tnormalizeArtifactPath(artifactPath), input);\n\t\treturn ok().build();\n\t}\n\t\n\t@Api(order=400, description = \"Delete artifact of specified path, or delete all artifacts \" +\n\t\t\t\"if artifact path is not specified\")\n\t@Path(\"/{buildId}{artifactPath:(/.*)?}\")\n\t@DELETE\n\tpublic Response deleteArtifact(\n\t\t\t@PathParam(\"buildId\") Long buildId, \n\t\t\t@PathParam(\"artifactPath\") @Api(example = \"/path/to/directoryOrFile\") String artifactPath) {\n\t\tBuild build = buildService.load(buildId);\n\t\tif (!SecurityUtils.canManageBuild(build))\n\t\t\tthrow new UnauthorizedException();\n\t\t\n\t\tbuildService.deleteArtifact(build, normalizeArtifactPath(artifactPath));","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/ArtifactResource.java#L82-L118","documentation":"Thrown by ArtifactResource.uploadArtifact when the authenticated user lacks manage-build permission on the build's project. Publishing artifacts requires SecurityUtils.canManageBuild(build), a stronger permission than mere project access.","triggerScenarios":"POST (upload) to /builds/{buildId}/artifacts/{artifactPath} by a user who can view but not manage the build; build-agent or job token with insufficient project role.","commonSituations":"Uploading artifacts from an external script with a read-only user; project role downgraded from maintainer to read; using personal access token of a non-member.","solutions":["Use credentials with Build Management permission on the project","Assign the job's token/user a role that allows managing builds (e.g. project maintainer)","If running inside a OneDev job, use the built-in build credential rather than a custom one"],"exampleFix":"// before\ncurl -u reader:token -X POST --data-binary @app.jar .../builds/42/artifacts/target/app.jar\n// after\ncurl -u maintainer:token -X POST --data-binary @app.jar .../builds/42/artifacts/target/app.jar","handlingStrategy":"validation","validationCode":"if (!canManageBuild(tokenUser, buildId)) throw new Error('manage-build permission required to upload artifacts');","typeGuard":"function canManage(u, b) { return u?.managedProjectIds?.includes(b?.projectId); }","tryCatchPattern":"try { uploadArtifact(buildId, path, stream); } catch (e) { if (/Unauthorized/i.test(e.message)) { throw new Error('Credential lacks Build Management permission'); } throw e; }","preventionTips":["Give CI service accounts at least maintainer role on their project","Prefer OneDev's built-in job token for artifact publishing","Verify permission scope of personal access tokens"],"tags":["rest","auth","artifact","upload"],"backgroundTag":"insufficient-permissions","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"}