apple/pkl · error · ConversionException

Error accessing constructor of class `%s`.

Error message

Error accessing constructor of class `%s`.

What it means

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).

Source

Thrown at pkl-config-java/src/main/java/org/pkl/config/java/mapper/PMapToMap.java:86

          });
    } catch (NoSuchMethodException e2) {
      try {
        // default constructor
        var ctor0 = lookup.findConstructor(clazz, MethodType.methodType(void.class));
        return Optional.of(
            length -> {
              try {
                //noinspection unchecked
                return (Map<K, V>) ctor0.invoke();
              } catch (Throwable t) {
                throw new ConversionException(
                    String.format("Error invoking constructor of class `%s`.", clazz), t);
              }
            });
      } catch (NoSuchMethodException e0) {
        return Optional.empty();
      } catch (IllegalAccessException e) {
        throw new ConversionException(
            String.format("Error accessing constructor of class `%s`.", clazz), e);
      }
    } catch (IllegalAccessException e) {
      throw new ConversionException(
          String.format("Error accessing constructor of class `%s`.", clazz), e);
    }
  }

  private static class ConverterImpl<K, V> implements Converter<Map<Object, Object>, Map<K, V>> {
    private final Function<Integer, Map<K, V>> targetInstantiator;
    private final Type targetKeyType;
    private final Type targetValueType;

    private PClassInfo<Object> cachedKeyType = PClassInfo.Unavailable;
    private @Nullable Converter<Object, K> cachedKeyConverter;

    private PClassInfo<Object> cachedValueType = PClassInfo.Unavailable;
    private @Nullable Converter<Object, V> cachedValueConverter;

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Make the target Map class and the constructor used public.
  2. 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.
  3. Use a public, standard Map implementation (HashMap, LinkedHashMap) as the conversion target.
  4. If targeting JDK internal map types, switch to a supported public class — strong encapsulation cannot be bypassed without unsafe flags.

Example fix

// before (module-info.java)
module my.app { }
// after
module my.app { opens my.collections; }
// and/or: public class InternalMap<K,V> extends LinkedHashMap<K,V> { public InternalMap() {} }
Defensive patterns

Strategy: validation

Validate before calling

// Check accessibility from the mapper's perspective before converting:
static boolean isAccessibleForLookup(Class<?> c) {
  int mods = c.getModifiers();
  return java.lang.reflect.Modifier.isPublic(mods)
      && (c.getModule().isOpen(c.getPackageName(), PMapToMapAccessibleProbe.class.getModule())
          || !c.getModule().isNamed());
}

Type guard

static boolean isPublicMapTarget(Type t) {
  Class<?> c = (t instanceof Class<?>) ? (Class<?>) t : (Class<?>) ((ParameterizedType) t).getRawType();
  return java.lang.reflect.Modifier.isPublic(c.getModifiers()) && Map.class.isAssignableFrom(c);
}

Try / catch

try {
  Map<String, Object> result = valueRenderer.render(pValue, targetType);
} catch (ConversionException e) {
  if (e.getMessage() != null && e.getMessage().contains("Error accessing constructor")) {
    log.warn(targetType + " not accessible to mapper; using HashMap instead");
    Map<String, Object> result = new java.util.HashMap<>(); // fallback
  } else throw e;
}

Prevention

When it happens

Trigger: 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)`.

Common situations: 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.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/45cc631c9ab820b4. Report an issue: GitHub.