pinpoint-apm/pinpoint · error · ConfigurationException

<fieldName> access error

Error message

<fieldName> access error

What it means

After successfully parsing the value, injectField() uses field.set(target, parsedValue) to write it into the @Value-annotated field. If this reflective operation fails (IllegalAccessException, or an exception due to final/static constraints), a ConfigurationException named 'ClassName.fieldName access error' is thrown with the original exception as cause. Note parse() never returns null, so this wrapper only fires on reflection failures.

Source

Thrown at commons-config/src/main/java/com/navercorp/pinpoint/common/config/util/ValueAnnotationProcessor.java:190

    private char parseChar(String value) {
        if (value.length() != 1) {
            throw new IllegalArgumentException("Invalid value:" + value);
        }
        return value.charAt(0);
    }

    private void injectField(Field field, Object target, String value) {
        final Class<?> fieldType = field.getType();

        try {
            final Object parsedValue = parse(fieldType, value);
            if (parsedValue != null) {
                try {
                    setAccessible(field);
                    field.set(target, parsedValue);
                } catch (ReflectiveOperationException e) {
                    throw new ConfigurationException(getFieldName(target, field) + " access error", e);
                }
            }
        } catch (Exception ex) {
            throw new RuntimeException("injectField error field:" + field + " value:" + value, ex);
        }
    }

    private String getFieldName(Object instance, Member field) {
        return instance.getClass().getSimpleName() + "." + field.getName();
    }

}

View on GitHub (pinned to 744c3d3075)

Solutions

  1. Remove the final/static modifiers from the @Value-annotated field
  2. Ensure the config class package is under com.navercorp.pinpoint and opened to the processor (add opens directives if using modules / --add-opens on the JVM)
  3. Convert the field to a package-private non-final field with a matching setter so handleMethods can inject via method.invoke instead

Example fix

// before
@Value("${log.level}")
private static final String logLevel;
// after
@Value("${log.level}")
private String logLevel;
Defensive patterns

Strategy: type-guard

Validate before calling

int mods = field.getModifiers();
if (java.lang.reflect.Modifier.isStatic(mods) || java.lang.reflect.Modifier.isFinal(mods)) {
    throw new IllegalStateException("@Value field must not be static/final: " + field);
}

Try / catch

try {
    processor.process(configInstance, resolver);
} catch (ConfigurationException e) {
    log.error("Reflection access failed for {}: cause={}", e.getMessage(), e.getCause(), e);
    throw e;
}

Prevention

When it happens

Trigger: field.set() fails for the annotated field — typically because the field is static final, lives under a package that blocks setAccessible under the module system / SecurityManager, or is otherwise inaccessible even after setAccessible(true).

Common situations: Running on JDK 9+ strong encapsulation where the config class package is not open to the processor's module; annotating a static final field expecting injection; security policies denying reflectAccess.

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 pinpoint-apm/pinpoint@744c3d3075 (2026-09-07). Data as JSON: /api/errors/fff008510e5d225b. Report an issue: GitHub.