{"record":{"id":"7b96d56390154e3e","repo":"halo-dev/halo","slug":"private-key-location-does-not-exist","errorCode":null,"errorMessage":"Private key location does not exist","messagePattern":"Private key location does not exist","errorType":"validation","errorClass":"InvalidConfigurationPropertyValueException","httpStatus":null,"severity":"critical","filePath":"application/src/main/java/run/halo/app/infra/properties/JwtProperties.java","lineNumber":119,"sourceCode":"\n    private RSAPublicKey readPublicKey() throws IOException {\n        String key = \"halo.security.oauth2.jwt.public-key-location\";\n        Assert.notNull(this.publicKeyLocation, \"PublicKeyLocation must not be null\");\n        if (!this.publicKeyLocation.exists()) {\n            throw new InvalidConfigurationPropertyValueException(\n                    key, this.publicKeyLocation, \"Public key location does not exist\");\n        }\n        try (InputStream inputStream = this.publicKeyLocation.getInputStream()) {\n            String source = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);\n            return RsaKeyConverters.x509().convert(new ByteArrayInputStream(source.getBytes()));\n        }\n    }\n\n    private RSAPrivateKey readPrivateKey() throws IOException {\n        String key = \"halo.security.oauth2.jwt.private-key-location\";\n        Assert.notNull(this.privateKeyLocation, \"PrivateKeyLocation must not be null\");\n        if (!this.privateKeyLocation.exists()) {\n            throw new InvalidConfigurationPropertyValueException(\n                    key, this.privateKeyLocation, \"Private key location does not exist\");\n        }\n        try (InputStream inputStream = this.privateKeyLocation.getInputStream()) {\n            String source = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);\n            return RsaKeyConverters.pkcs8().convert(new ByteArrayInputStream(source.getBytes()));\n        }\n    }\n}\n","sourceCodeStart":101,"sourceCodeEnd":128,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/infra/properties/JwtProperties.java#L101-L128","documentation":"Thrown as InvalidConfigurationPropertyValueException from JwtProperties.readPrivateKey during bean construction when halo.security.oauth2.jwt.private-key-location points at a Resource whose exists()==false. The private key (PKCS#8 PEM) is required to sign issued JWTs, so startup cannot proceed.","triggerScenarios":"Startup with the private-key property set to a non-existent Resource: wrong path, unmounted volume, missing classpath entry, or a file not deployed to the container.","commonSituations":"Container deployment missing the mounted secrets volume; typo in path; key generated elsewhere and not copied; environment-specific path differences; file git-ignored from the build.","solutions":["Correct halo.security.oauth2.jwt.private-key-location to the actual resource location.","Mount/copy the PKCS#8 PEM private key into the runtime at the configured path.","Use classpath: for packaged keys or file: for mounted secrets.","Confirm the file is in PKCS#8 DER/PEM form and readable by the process."],"exampleFix":"# before\nhalo.security.oauth2.jwt.private-key-location=file:./halo.pem\n\n# after\nhalo.security.oauth2.jwt.private-key-location=file:/etc/halo/keys/jwt-private.pem","handlingStrategy":"validation","validationCode":"Resource r = resourceLoader.getResource(privateKeyLocation);\nif (!r.exists()) {\n    throw new IllegalStateException(\"Private key resource missing: \" + privateKeyLocation);\n}","typeGuard":"static boolean resourceExists(Resource r) {\n    return r != null && r.exists();\n}","tryCatchPattern":"try {\n    new JwtProperties(issuer, algo, pubRes, privRes);\n} catch (InvalidConfigurationPropertyValueException e) {\n    log.error(\"Configure halo.security.oauth2.jwt.private-key-location to an existing PKCS#8 resource\", e);\n    throw e;\n}","preventionTips":["Mount secrets volumes in containers and verify at deploy time.","Store keys outside the image; never bake production keys into the JAR.","Validate key resource paths in CI against the target environment."],"tags":["security","jwt","configuration","startup","rsa-key"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}