{"record":{"id":"45cc631c9ab820b4","repo":"apple/pkl","slug":"error-accessing-constructor-of-class-s-45cc63","errorCode":null,"errorMessage":"Error accessing constructor of class `%s`.","messagePattern":"Error accessing constructor of class `(.+?)`\\.","errorType":"exception","errorClass":"ConversionException","httpStatus":null,"severity":"error","filePath":"pkl-config-java/src/main/java/org/pkl/config/java/mapper/PMapToMap.java","lineNumber":86,"sourceCode":"          });\n    } catch (NoSuchMethodException e2) {\n      try {\n        // default constructor\n        var ctor0 = lookup.findConstructor(clazz, MethodType.methodType(void.class));\n        return Optional.of(\n            length -> {\n              try {\n                //noinspection unchecked\n                return (Map<K, V>) ctor0.invoke();\n              } catch (Throwable t) {\n                throw new ConversionException(\n                    String.format(\"Error invoking constructor of class `%s`.\", clazz), t);\n              }\n            });\n      } catch (NoSuchMethodException e0) {\n        return Optional.empty();\n      } catch (IllegalAccessException e) {\n        throw new ConversionException(\n            String.format(\"Error accessing constructor of class `%s`.\", clazz), e);\n      }\n    } catch (IllegalAccessException e) {\n      throw new ConversionException(\n          String.format(\"Error accessing constructor of class `%s`.\", clazz), e);\n    }\n  }\n\n  private static class ConverterImpl<K, V> implements Converter<Map<Object, Object>, Map<K, V>> {\n    private final Function<Integer, Map<K, V>> targetInstantiator;\n    private final Type targetKeyType;\n    private final Type targetValueType;\n\n    private PClassInfo<Object> cachedKeyType = PClassInfo.Unavailable;\n    private @Nullable Converter<Object, K> cachedKeyConverter;\n\n    private PClassInfo<Object> cachedValueType = PClassInfo.Unavailable;\n    private @Nullable Converter<Object, V> cachedValueConverter;","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-config-java/src/main/java/org/pkl/config/java/mapper/PMapToMap.java#L68-L104","documentation":"When PMapToMap tries to obtain a MethodHandle for the target Map class's constructors via MethodHandles.Lookup.findConstructor, an IllegalAccessException means the constructor exists but is not accessible from PMapToMap's lookup context (e.g. the class or constructor is private/package-private and not opened to this package). The library rethrows it as this ConversionException at either lookup site (the (int,float) constructor lookup or the default-constructor lookup).","triggerScenarios":"Mapping a Pkl Map to a Map subtype whose constructors are private, package-private, or whose declaring class is in a non-opened module/package, e.g. converting to a package-private `InternalMap` class from another package via `ValueRenderer.render(value, InternalMap.class)`.","commonSituations":"Java 9+ strong encapsulation: targeting classes in another module (e.g. JDK internals or an unopened library module); package-private custom map classes in a different package; builder-pattern classes that hide constructors as private.","solutions":["Make the target Map class and the constructor used public.","If the class is in your own JPMS module, add `opens your.package;` (or `opens your.package to org.pkl.config.java;`) in module-info.java so MethodHandles.Lookup can access the constructor.","Use a public, standard Map implementation (HashMap, LinkedHashMap) as the conversion target.","If targeting JDK internal map types, switch to a supported public class — strong encapsulation cannot be bypassed without unsafe flags."],"exampleFix":"// before (module-info.java)\nmodule my.app { }\n// after\nmodule my.app { opens my.collections; }\n// and/or: public class InternalMap<K,V> extends LinkedHashMap<K,V> { public InternalMap() {} }\n","handlingStrategy":"validation","validationCode":"// Check accessibility from the mapper's perspective before converting:\nstatic boolean isAccessibleForLookup(Class<?> c) {\n  int mods = c.getModifiers();\n  return java.lang.reflect.Modifier.isPublic(mods)\n      && (c.getModule().isOpen(c.getPackageName(), PMapToMapAccessibleProbe.class.getModule())\n          || !c.getModule().isNamed());\n}","typeGuard":"static boolean isPublicMapTarget(Type t) {\n  Class<?> c = (t instanceof Class<?>) ? (Class<?>) t : (Class<?>) ((ParameterizedType) t).getRawType();\n  return java.lang.reflect.Modifier.isPublic(c.getModifiers()) && Map.class.isAssignableFrom(c);\n}","tryCatchPattern":"try {\n  Map<String, Object> result = valueRenderer.render(pValue, targetType);\n} catch (ConversionException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Error accessing constructor\")) {\n    log.warn(targetType + \" not accessible to mapper; using HashMap instead\");\n    Map<String, Object> result = new java.util.HashMap<>(); // fallback\n  } else throw e;\n}","preventionTips":["Make conversion-target classes and their constructors public.","In JPMS modules, `opens` every package holding mapping-target classes.","Avoid package-private or private nested Map classes as conversion targets.","Test conversions on JPMS classpath setups matching production (module path vs classpath changes accessibility)."],"tags":["java","reflection","access-denied","jpms","map-conversion"],"backgroundTag":"permission-denied","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}