{"id":"f8f512eb3e8c592c","repo":"square/retrofit","slug":"context-null","errorCode":null,"errorMessage":"context == null","messagePattern":"context == null","errorType":"exception","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"retrofit-converters/jaxb/src/main/java/retrofit2/converter/jaxb/JaxbConverterFactory.java","lineNumber":45,"sourceCode":"import retrofit2.Converter;\nimport retrofit2.Retrofit;\n\n/**\n * A {@linkplain Converter.Factory converter} which uses JAXB for XML. All validation events are\n * ignored.\n */\npublic final class JaxbConverterFactory extends Converter.Factory {\n  static final MediaType XML = MediaType.get(\"application/xml; charset=utf-8\");\n\n  /** Create an instance using a default {@link JAXBContext} instance for conversion. */\n  public static JaxbConverterFactory create() {\n    return new JaxbConverterFactory(null);\n  }\n\n  /** Create an instance using {@code context} for conversion. */\n  @SuppressWarnings(\"ConstantConditions\") // Guarding public API nullability.\n  public static JaxbConverterFactory create(JAXBContext context) {\n    if (context == null) throw new NullPointerException(\"context == null\");\n    return new JaxbConverterFactory(context);\n  }\n\n  /** If null, a new JAXB context will be created for each type to be converted. */\n  private final @Nullable JAXBContext context;\n\n  private JaxbConverterFactory(@Nullable JAXBContext context) {\n    this.context = context;\n  }\n\n  @Override\n  public @Nullable Converter<?, RequestBody> requestBodyConverter(\n      Type type,\n      Annotation[] parameterAnnotations,\n      Annotation[] methodAnnotations,\n      Retrofit retrofit) {\n    if (type instanceof Class && ((Class<?>) type).isAnnotationPresent(XmlRootElement.class)) {\n      return new JaxbRequestConverter<>(contextForType((Class<?>) type), (Class<?>) type);","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/square/retrofit/blob/d0b112dad073b7fe49c953ebc46ff1b424cb1e51/retrofit-converters/jaxb/src/main/java/retrofit2/converter/jaxb/JaxbConverterFactory.java#L27-L63","documentation":"NullPointerException thrown by JaxbConverterFactory.create(JAXBContext) when the supplied context is null (line 45). Note this only applies to the explicit-argument factory: the no-arg create() intentionally passes null to the private constructor (line 39) to mean 'create a fresh JAXBContext per type' (see contextForType at line 79). The guard therefore only rejects an explicit null passed by the caller, failing fast rather than NPE-ing later.","triggerScenarios":"Calling `JaxbConverterFactory.create(context)` where `context` is null. Distinguish from the legitimate `JaxbConverterFactory.create()` no-arg call, which is fine and produces the per-type lazy behavior.","commonSituations":"DI-provided JAXBContext bean missing or failed to build (e.g. JAXBException during context creation swallowed); a helper returning null when the context could not be constructed; passing null by mistake intending the default; JDK 9+ module access issues causing JAXBContext.newInstance to fail upstream and yielding null in calling code.","solutions":["If you want default per-type context creation, call the no-arg `JaxbConverterFactory.create()` instead of passing null.","If you need a shared context, build one explicitly: `JAXBContext.newInstance(MyType.class)` and ensure it is non-null before passing (it throws JAXBException on failure, so catch and handle, do not null-out).","On JDK 9+, add `--add-modules java.xml.bind` (or ship the jakarta.xml.bind API/impl) so JAXBContext.newInstance succeeds rather than returning null/throwing."],"exampleFix":"// before\nJAXBContext ctx = buildContextOrNull(); // null when construction failed\nRetrofit retrofit = new Retrofit.Builder()\n    .addConverterFactory(JaxbConverterFactory.create(ctx))\n    .build();\n\n// after — use the no-arg factory for per-type lazy contexts\nRetrofit retrofit = new Retrofit.Builder()\n    .addConverterFactory(JaxbConverterFactory.create())\n    .build();","handlingStrategy":"validation","validationCode":"// Distinguish the legitimate no-arg factory (lazy per-type context) from an\n// explicit shared context, and never pass an explicit null.\nJAXBContext ctx = buildSharedContext(); // returns non-null or throws JAXBException\nJaxbConverterFactory factory = (ctx != null)\n    ? JaxbConverterFactory.create(ctx)\n    : JaxbConverterFactory.create(); // default, per-type lazy context","typeGuard":null,"tryCatchPattern":"try {\n  factory = (context != null)\n      ? JaxbConverterFactory.create(context)\n      : JaxbConverterFactory.create();\n} catch (NullPointerException e) {\n  throw new IllegalStateException(\n      \"JAXBContext was null; use create() for the default per-type context\", e);\n}","preventionTips":["Call the no-arg JaxbConverterFactory.create() if you want per-type lazy contexts; never pass null explicitly.","When sharing a context, build it with JAXBContext.newInstance(Type.class) and let JAXBException propagate instead of catching it into null.","On JDK 9+, ensure java.xml.bind (or jakarta.xml.bind) is on the module path so context creation succeeds.","Bind any shared JAXBContext bean as non-optional in your DI framework."],"tags":["jaxb","retrofit","converter","null-safety","configuration","xml"],"analyzedSha":"d0b112dad073b7fe49c953ebc46ff1b424cb1e51","analyzedAt":"2026-08-04T19:12:59.096Z","schemaVersion":2}