{"record":{"id":"b609c63fe661314a","repo":"apache/cordova-android","slug":"unable-to-determine-android-sdk-directory","errorCode":null,"errorMessage":"Unable to determine Android SDK directory.","messagePattern":"Unable to determine Android SDK directory\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"framework/cordova.gradle","lineNumber":119,"sourceCode":"        Properties properties = new Properties()\n        localProperties.withInputStream { instr ->\n            properties.load(instr)\n        }\n        def sdkDirProp = properties.getProperty('sdk.dir')\n        if (sdkDirProp != null) {\n            androidSdkDir = sdkDirProp\n        } else {\n            sdkDirProp = properties.getProperty('android.dir')\n            if (sdkDirProp != null) {\n                androidSdkDir = (new File(rootDir, sdkDirProp)).getAbsolutePath()\n            }\n        }\n    }\n    if (androidSdkDir == null && systemProperty != null) {\n        androidSdkDir = systemProperty\n    }\n    if (androidSdkDir == null) {\n        throw new RuntimeException(\n            \"Unable to determine Android SDK directory.\")\n    }\n    androidSdkDir\n}\n\ndef doExtractIntFromManifest(name) {\n    def manifestFile = file(android.sourceSets.main.manifest.srcFile)\n    def pattern = Pattern.compile(name + \"=\\\"(\\\\d+)\\\"\")\n    def matcher = pattern.matcher(manifestFile.getText())\n    matcher.find()\n    return new BigInteger(matcher.group(1))\n}\n\ndef doGetConfigXml() {\n    def xml = file(\"src/main/res/xml/config.xml\").getText()\n    // Disable namespace awareness since Cordova doesn't use them properly\n    return new XmlParser(false, false).parseText(xml)\n}","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/apache/cordova-android/blob/7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3/framework/cordova.gradle#L101-L137","documentation":"getAndroidSdkDir resolves the Android SDK in priority order: ANDROID_HOME env var, ANDROID_SDK_ROOT env var, then local.properties at the project root (sdk.dir, or legacy android.dir resolved against rootDir — only consulted when no env var is set), then the android.home system property. If every source yields null, this RuntimeException is thrown. Note that a present-but-wrong env var is NOT this error — it produces a build-tools error later; this fires only when all four sources are absent.","triggerScenarios":"Building in a shell/CI job where neither ANDROID_HOME nor ANDROID_SDK_ROOT is exported; a fresh clone on a new machine — local.properties is deliberately .gitignored, so it does not exist; building the framework without passing -Dandroid.home.","commonSituations":"CI pipelines that install the SDK but forget to export ANDROID_HOME in the job step; new teammates' first build; scripts that sanitize the environment; Linux case mismatches in the env var value are a sibling problem (dir not found) rather than this one.","solutions":["Create platforms/android/local.properties (or the repo-root local.properties for the framework build) containing sdk.dir=/absolute/path/to/android-sdk — use forward slashes on Windows or escape the backslashes and colon.","Or export ANDROID_HOME (and ANDROID_SDK_ROOT) in the shell / CI environment pointing at the SDK root.","Or pass it per invocation: ./gradlew -Dandroid.home=/path/to/sdk assembleDebug.","On CI, prefer env vars, since local.properties is machine-specific and should not be committed."],"exampleFix":"# before — no SDK source configured\n$ ./gradlew assembleDebug\n... Unable to determine Android SDK directory.\n\n# after (option 1 — machine-local file)\n$ printf 'sdk.dir=/opt/android-sdk\\n' > platforms/android/local.properties\n# after (option 2 — environment)\n$ export ANDROID_HOME=/opt/android-sdk && ./gradlew assembleDebug","handlingStrategy":"validation","validationCode":"# Verify an SDK source exists and points at a real SDK before building\nSDK=\"${ANDROID_HOME:-${ANDROID_SDK_ROOT:-}}\"\nif [ -z \"$SDK\" ] && [ -f platforms/android/local.properties ]; then\n  SDK=$(sed -n 's/^sdk.dir=//p' platforms/android/local.properties | head -1)\nfi\n[ -n \"$SDK\" ] && [ -d \"$SDK/build-tools\" ] \\\n  || { echo 'No Android SDK location — export ANDROID_HOME or write sdk.dir to platforms/android/local.properties'; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Export ANDROID_HOME and ANDROID_SDK_ROOT in your shell profile and in every CI job definition.","Never rely on a committed local.properties — it is machine-specific and gitignored by design.","Verify the path's case and spelling on Linux (~/Android/Sdk vs ~/android-sdk) when pointing env vars."],"tags":["android-sdk","environment","gradle","ci","local-properties"],"backgroundTag":"android-sdk-location-not-found","analyzedSha":"7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3","analyzedAt":"2026-08-22T04:57:58.868Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}