{"record":{"id":"84454b61c7dbbc88","repo":"alibaba/ARouter","slug":"the-field-fieldname-is-null-in-class-classn","errorCode":null,"errorMessage":"The field '<fieldName>' is null, in class '<className>!","messagePattern":"The field '<fieldName>' is null, in class '<className>!","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java","lineNumber":171,"sourceCode":"                                    \"substitute.\" + fieldName + \" = $T.getInstance().navigation($T.class)\",\n                                    ARouterClass,\n                                    ClassName.get(element.asType())\n                            );\n                        } else {    // use byName\n                            // Getter\n                            injectMethodBuilder.addStatement(\n                                    \"substitute.\" + fieldName + \" = ($T)$T.getInstance().build($S).navigation()\",\n                                    ClassName.get(element.asType()),\n                                    ARouterClass,\n                                    fieldConfig.name()\n                            );\n                        }\n\n                        // Validator\n                        if (fieldConfig.required()) {\n                            injectMethodBuilder.beginControlFlow(\"if (substitute.\" + fieldName + \" == null)\");\n                            injectMethodBuilder.addStatement(\n                                    \"throw new RuntimeException(\\\"The field '\" + fieldName + \"' is null, in class '\\\" + $T.class.getName() + \\\"!\\\")\", ClassName.get(parent));\n                            injectMethodBuilder.endControlFlow();\n                        }\n                    } else {    // It's normal intent value\n                        String paramName = StringUtils.isEmpty(fieldConfig.name()) ? fieldName : fieldConfig.name();\n                        int type = typeUtils.typeExchange(element);\n\n                        injectMethodBuilder.beginControlFlow(\"if (null != bundle && bundle.containsKey($S))\", paramName);\n                        if (type == TypeKind.OBJECT.ordinal()) {\n                            injectMethodBuilder.beginControlFlow(\"if (null != serializationService)\");\n                            TypeName fieldType = TypeName.get(element.asType());\n                            String valueName = fieldName + \"Value\";\n                            injectMethodBuilder.addStatement(\n                                    \"$T \" + valueName + \" = serializationService.parseObject(bundle.getString($S), new $T<$T>(){}.getType())\",\n                                    fieldType,\n                                    paramName,\n                                    TypeWrapperClass,\n                                    fieldType\n                            );","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/alibaba/ARouter/blob/84f451d244e3fb1d0e37801de1b9ee2af2f81d68/arouter-compiler/src/main/java/com/alibaba/android/arouter/compiler/processor/AutowiredProcessor.java#L153-L189","documentation":"When an @Autowired field is declared with required = true, the generated injection code throws RuntimeException at runtime if the field is still null after injection. This is a fail-fast validator so missing navigation arguments surface immediately instead of causing NPEs later.","triggerScenarios":"Navigating to an Activity/Fragment without putting the required parameter: ARouter.with(...).navigation() omitting withString/withInt for a field marked @Autowired(required = true), or opening the target from outside ARouter (deep link, notification) without the extras.","commonSituations":"Deep links or push intents that skip the ARouter builder and its typed params; refactoring a route name and forgetting a call site's withString; optional-in-practice params wrongly marked required = true.","solutions":["Pass the required parameter at every navigation call site: ARouter.getInstance().build(path).withString(\"name\", value)","Make the field optional by removing required = true if it can legitimately be absent","For external entry points, ensure the intent extras carry all required keys, or route external opens through ARouter","Guard nullable fields in code and log the missing key to find the offending caller"],"exampleFix":"// before\nARouter.getInstance().build(\"/user/detail\").navigation(); // RuntimeException: field 'userId' is null\n// after\nARouter.getInstance().build(\"/user/detail\")\n        .withString(\"userId\", userId)\n        .navigation();","handlingStrategy":"validation","validationCode":"// before navigating, ensure required params are supplied\npublic static void navToUserDetail(String userId) {\n    if (userId == null || userId.isEmpty()) {\n        Log.w(TAG, \"userId required for /user/detail\");\n        return;\n    }\n    ARouter.getInstance().build(\"/user/detail\").withString(\"userId\", userId).navigation();\n}","typeGuard":null,"tryCatchPattern":"try {\n    ARouter.getInstance().build(path).withString(\"userId\", userId).navigation();\n} catch (RuntimeException e) {\n    Log.e(TAG, \"Missing required autowired field\", e);\n}","preventionTips":["Match every @Autowired(required = true) field with a withXxx call at all call sites","Route external deep links through ARouter so required extras are enforced","Set required = true only for genuinely mandatory params","Log a breadcrumb of navigation calls to trace which call site omitted a param"],"tags":["android","arouter","autowired","null","runtime"],"backgroundTag":"missing-required-argument","analyzedSha":"84f451d244e3fb1d0e37801de1b9ee2af2f81d68","analyzedAt":"2026-09-06T13:30:41.084Z","contentChangedAt":"2026-09-06T13:30:41.084Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}