{"record":{"id":"2902cf0c2c2b815d","repo":"Tencent/matrix","slug":"tag-the-path-of-tool-nm-is-not-given","errorCode":null,"errorMessage":"TAG + \"---The path of tool 'nm' is not given!\"","messagePattern":"TAG \\+ \"---The path of tool 'nm' is not given!\"","errorType":"exception","errorClass":"TaskInitException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnStrippedSoCheckTask.java","lineNumber":67,"sourceCode":"public class UnStrippedSoCheckTask extends ApkTask {\n\n    private static final String TAG = \"Matrix.UnStrippedSoCheckTask\";\n\n    private File libDir;\n    private String toolnmPath;\n\n    public UnStrippedSoCheckTask(JobConfig jobConfig, Map<String, String> params) {\n        super(jobConfig, params);\n        type = TASK_TYPE_UNSTRIPPED_SO;\n    }\n\n    @Override\n    public void init() throws TaskInitException {\n        super.init();\n        final String inputPath = config.getUnzipPath();\n        toolnmPath = params.get(JobConstants.PARAM_TOOL_NM);\n        if (Util.isNullOrNil(toolnmPath)) {\n            throw new TaskInitException(TAG + \"---The path of tool 'nm' is not given!\");\n        } else {\n            Pattern envPattern = Pattern.compile(\"(\\\\$[a-zA-Z_-]+)\");\n            Matcher matcher =  envPattern.matcher(toolnmPath);\n            while (matcher.find()) {\n                if (!Util.isNullOrNil(matcher.group())) {\n                    String env = System.getenv(matcher.group().substring(1));\n                    Log.d(TAG, \"%s -> %s\", matcher.group().substring(1), env);\n                    if (!Util.isNullOrNil(env)) {\n                        toolnmPath = toolnmPath.replace(matcher.group(), env);\n                    }\n                }\n            }\n            Log.i(TAG, \"toolnm pah is %s\", toolnmPath);\n        }\n        if (!FileUtil.isLegalFile(toolnmPath)) {\n            throw new TaskInitException(TAG + \"---Can not find the tool 'nm'!\");\n        }\n        if (!Util.isNullOrNil(inputPath)) {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-apk-canary/src/main/java/com/tencent/matrix/apk/model/task/UnStrippedSoCheckTask.java#L49-L85","documentation":"UnStrippedSoCheckTask.init() throws TaskInitException when the required external 'nm' (GNU nm symbol-listing) tool path parameter is missing or empty. This task shells out to nm to detect unstripped .so files, so it cannot start without it. Thrown before any APK analysis begins.","triggerScenarios":"Calling the apk-canary job with PARAM_TOOL_NM unset, empty, or null in the task params map.","commonSituations":"Running the so-stripping check in a fresh CI environment where the Android NDK path was never configured; migrating matrix config and dropping the tool parameter; forgetting that the nm tool path must be provided (Linux/macOS).","solutions":["Pass the nm binary path via the task params, e.g. params.put(JobConstants.PARAM_TOOL_NM, \"/usr/bin/nm\") or the NDK toolchain nm (NDK .../toolchains/llvm/prebuilt/<host>/bin/llvm-nm).","Install binutils/NDK if nm is not present and set the resulting absolute path.","Verify via `which nm` that the path exists and is executable before launching the job.","If using $ENV_VAR style in the configured path, ensure the env var is exported in the environment running matrix (the task resolves $(VAR) patterns via System.getenv)."],"exampleFix":"// before\nMap<String, String> params = new HashMap<>();\n// after\nparams.put(JobConstants.PARAM_TOOL_NM, \"/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-nm\");","handlingStrategy":"validation","validationCode":"String nm = params.get(JobConstants.PARAM_TOOL_NM);\nif (nm == null || nm.trim().isEmpty()) {\n    throw new IllegalArgumentException(\"PARAM_TOOL_NM must be set to an absolute nm/llvm-nm path\");\n}\nif (!new File(nm).canExecute()) throw new IllegalArgumentException(\"nm not executable: \" + nm);","typeGuard":null,"tryCatchPattern":"try {\n    job.run();\n} catch (TaskInitException e) {\n    if (e.getMessage().contains(\"tool 'nm' is not given\")) {\n        configureNmToolPath();\n    } else throw e;\n}","preventionTips":["Always configure PARAM_TOOL_NM (prefer the NDK llvm-nm) in a shared matrix config file.","Smoke-test the nm path with a new File(path).canExecute() check in build setup.","Document NDK/binutils prerequisites for CI images.","Export any env vars referenced via $VAR in the tool path."],"tags":["android","apk-canary","missing-tool","config"],"backgroundTag":"missing-required-config-field","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}