{"id":"10f98fcc595bf3af","repo":"google/gson","slug":"failed-invoking-canaccess","errorCode":null,"errorMessage":"Failed invoking canAccess","messagePattern":"Failed invoking canAccess","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java","lineNumber":98,"sourceCode":"\n  private abstract static class AccessChecker {\n    static final AccessChecker INSTANCE;\n\n    static {\n      AccessChecker accessChecker = null;\n      // TODO: Ideally should use Multi-Release JAR for this version specific code\n      if (JavaVersion.isJava9OrLater()) {\n        try {\n          Method canAccessMethod =\n              AccessibleObject.class.getDeclaredMethod(\"canAccess\", Object.class);\n          accessChecker =\n              new AccessChecker() {\n                @Override\n                public boolean canAccess(AccessibleObject accessibleObject, Object object) {\n                  try {\n                    return (Boolean) canAccessMethod.invoke(accessibleObject, object);\n                  } catch (Exception e) {\n                    throw new RuntimeException(\"Failed invoking canAccess\", e);\n                  }\n                }\n              };\n        } catch (NoSuchMethodException ignored) {\n          // OK: will assume everything is accessible\n        }\n      }\n\n      if (accessChecker == null) {\n        accessChecker =\n            new AccessChecker() {\n              @Override\n              public boolean canAccess(AccessibleObject accessibleObject, Object object) {\n                // Cannot determine whether object can be accessed, so assume it can be accessed\n                return true;\n              }\n            };\n      }","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/google/gson/blob/8b8628c65699bc4421696183c62ae0c1b9b281dc/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java#L80-L116","documentation":"Thrown when Gson's Java 9+ access checker cannot invoke AccessibleObject.canAccess(Object) via reflection. The wrapper 'Failed invoking canAccess' re-throws the underlying reflective invocation failure as a RuntimeException because Gson needs to know whether a field/method is accessible before using it, and an unexpected exception from canAccess itself is unrecoverable. The {c} placeholder is not interpolated here; the message is literal and the original exception is attached as the cause.","triggerScenarios":"Occurs on Java 9+ only. The static initializer found AccessibleObject.canAccess and built the Java9 AccessChecker, but at runtime canAccessMethod.invoke(accessibleObject, object) threw (e.g. IllegalAccessException after the calling module lost access, a SecurityManager denying reflect access, or passing an object whose type mismatches the accessible object's declaring class for instance member checks).","commonSituations":"Running Gson under a strict JPMS setup without --add-opens to java.base; a SecurityManager that blocks reflective invocation; custom JVMs (GraalVM Native Image, some embedded runtimes) where canAccess behaves unexpectedly; concurrent classloading edge cases.","solutions":["If using JPMS, add the required opens, e.g. run with --add-opens java.base/java.lang=ALL-UNNAMED (and opens for every package containing reflected classes), or declare them in module-info.","Check the attached cause in the stack trace to identify the exact reflective failure (IllegalAccessException vs SecurityException vs IllegalArgumentException) and address that root cause.","Disable the module/SecurityManager restriction, or run on a standard JDK where canAccess is reachable.","If you cannot fix the environment, register a custom ReflectionAccessFilter returning BLOCK_INCLUSIVE_ALTERNATIVES / SERIALIZABLE or avoid reflective field access by registering explicit TypeAdapters for the affected types."],"exampleFix":"// before: java ... -jar app.jar  (canAccess invoke fails under JPMS)\n\n// after: grant reflective access at launch\njava --add-opens java.base/java.util=ALL-UNNAMED \\\n     --add-opens com.example.data/com.example.data.model=ALL-UNNAMED \\\n     -jar app.jar","handlingStrategy":"try-catch","validationCode":"// Before reflective heavy use, sanity-check module access at startup\ntry {\n  java.lang.reflect.Method m = AccessibleObject.class.getDeclaredMethod(\"canAccess\", Object.class);\n  Field f = MyClass.class.getDeclaredField(\"x\");\n  m.invoke(f, new MyClass()); // will throw if access is blocked\n} catch (Exception e) {\n  throw new IllegalStateException(\"Gson reflective access blocked; add the required --add-opens\", e);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return gson.fromJson(json, MyClass.class);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Failed invoking canAccess\")) {\n    throw new ConfigurationException(\"Gson cannot perform reflective access; launch JVM with --add-opens ...\", e);\n  }\n  throw e;\n}","preventionTips":["Document the required --add-opens entries in your launch script and Dockerfile.","Prefer registering explicit TypeAdapter / InstanceCreator instances over relying on reflective field access.","Run a startup self-test that triggers Gson reflection once so configuration failures surface at boot, not deep in a request."],"tags":["reflection","java-modules","jpms","security-manager","runtime"],"analyzedSha":"8b8628c65699bc4421696183c62ae0c1b9b281dc","analyzedAt":"2026-08-04T19:12:22.202Z","schemaVersion":2}