{"record":{"id":"cc29ebc63039a405","repo":"oracle/graal","slug":"sealing-violation-can-t-seal-package-s-already","errorCode":null,"errorMessage":"Sealing violation: can't seal package %s: already loaded","messagePattern":"Sealing violation: can't seal package (.+?): already loaded","errorType":"exception","errorClass":"SecurityException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccessClassLoader.java","lineNumber":505,"sourceCode":"            CodeSigner[] signers = res.getCodeSigners();\n            CodeSource cs = new CodeSource(url, signers);\n            return defineClass(name, b, 0, b.length, cs);\n        }\n    }\n\n    /**\n     * See {@code java.net.URLClassLoader#getAndVerifyPackage}.\n     */\n    private Package getAndVerifyPackage(String pkgname, Manifest man, URL url) {\n        Package pkg = getDefinedPackage(pkgname);\n        if (pkg != null) {\n            if (pkg.isSealed()) {\n                if (!pkg.isSealed(url)) {\n                    throw new SecurityException(\"Sealing violation: package \" + pkgname + \" is sealed\");\n                }\n            } else {\n                if ((man != null) && isSealed(pkgname, man)) {\n                    throw new SecurityException(\"Sealing violation: can't seal package \" + pkgname + \": already loaded\");\n                }\n            }\n        }\n        return pkg;\n    }\n\n    /**\n     * See {@code java.net.URLClassLoader#definePackage}.\n     */\n    private Package definePackage(String name, Manifest man, URL url) {\n        String specTitle = null;\n        String specVersion = null;\n        String specVendor = null;\n        String implTitle = null;\n        String implVersion = null;\n        String implVendor = null;\n        String sealed = null;\n        URL sealBase = null;","sourceCodeStart":487,"sourceCodeEnd":523,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.hostvmaccess/src/jdk/graal/compiler/hostvmaccess/HostVMAccessClassLoader.java#L487-L523","documentation":"Companion of the sealed-package check: if the package was previously defined WITHOUT sealing, JPMS/URLClassLoader semantics forbid sealing it later. When a second jar's manifest declares the package sealed (isSealed(pkgname, man) is true) but the already-loaded package is unsealed, this SecurityException is thrown — package sealing must be consistent from first definition.","triggerScenarios":"First class-path entry defines classes in package P with an unsealed (or absent) manifest; a later entry also contains package P and its manifest marks P as sealed. getAndVerifyPackage hits the else-branch: pkg exists, not sealed, but new manifest seals it.","commonSituations":"Mixing an original dependency jar with a repackaged/signed version that adds 'Sealed: true'; incremental builds where a rebuilt jar gains sealing metadata while stale classes from the unsealed original are still on the path.","solutions":["Make sealing consistent: remove 'Sealed: true' from the later jar's manifest, or ensure the FIRST jar that defines the package is the sealed one","Drop one of the two jars so the package is defined from a single source","Rebuild the artifact set so all entries for that package come from one manifest configuration"],"exampleFix":"# before\nclasspath: lib-core.jar     # unsealed, defines com.acme.api first\nclasspath: lib-secure.jar   # manifest: Sealed: true for com.acme.api -> SecurityException\n\n# after\nclasspath: lib-core.jar     # single, consistent source for com.acme.api","handlingStrategy":"validation","validationCode":"static void checkSealingConsistency(List<Path> classpath) throws IOException {\n    Map<String, String> pkgFirstSource = new HashMap<>();\n    for (Path jar : classpath) {\n        try (JarFile jf = new JarFile(jar.toFile())) {\n            Manifest man = jf.getManifest();\n            boolean seals = man != null && Boolean.parseBoolean(man.getMainAttributes().getValue(\"Sealed\"));\n            Enumeration<JarEntry> es = jf.entries();\n            while (es.hasMoreElements()) {\n                String n = es.nextElement().getName();\n                if (n.endsWith(\".class\")) {\n                    String pkg = n.substring(0, Math.max(0, n.lastIndexOf('/'))).replace('/', '.');\n                    pkgFirstSource.merge(pkg, seals ? \"sealed\" : \"open\", (a, b) -> a.equals(b) ? a : \"CONFLICT:\" + pkg);\n                }\n            }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"catch (SecurityException e) { if (e.getMessage().contains(\"already loaded\")) { align 'Sealed' attributes across the jars sharing the package or drop one jar; } }","preventionTips":["Make the Sealed manifest attribute consistent (present or absent) across all jars sharing a package","Rebuild artifact sets atomically instead of mixing old and new versions on one class path","Automate manifest audits in CI for image builds with multi-jar class paths"],"tags":["graalvm","classpath","sealed-package","security","manifest"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}