{"id":"dca8a8f604ce61ae","repo":"pypa/pip","slug":"on-non-android-platforms-the-api-level-and-abi-ar","errorCode":null,"errorMessage":"on non-Android platforms, the api_level and abi arguments are required","messagePattern":"on non-Android platforms, the api_level and abi arguments are required","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/tags.py","lineNumber":745,"sourceCode":"\n\ndef android_platforms(\n    api_level: int | None = None, abi: str | None = None\n) -> Iterator[str]:\n    \"\"\"\n    Yields the :attr:`~Tag.platform` tags for Android. If this function is invoked on\n    non-Android platforms, the ``api_level`` and ``abi`` arguments are required.\n\n    :param int api_level: The maximum `API level\n        <https://developer.android.com/tools/releases/platforms>`__ to return. Defaults\n        to the current system's version, as returned by ``platform.android_ver``.\n    :param str abi: The `Android ABI <https://developer.android.com/ndk/guides/abis>`__,\n        e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned by\n        ``sysconfig.get_platform``. Hyphens and periods will be replaced with\n        underscores.\n    \"\"\"\n    if platform.system() != \"Android\" and (api_level is None or abi is None):\n        raise TypeError(\n            \"on non-Android platforms, the api_level and abi arguments are required\"\n        )\n\n    if api_level is None:\n        # Python 3.13 was the first version to return platform.system() == \"Android\",\n        # and also the first version to define platform.android_ver().\n        api_level = platform.android_ver().api_level  # type: ignore[attr-defined]\n\n    if abi is None:\n        abi = sysconfig.get_platform().split(\"-\")[-1]\n    abi = _normalize_string(abi)\n\n    # 16 is the minimum API level known to have enough features to support CPython\n    # without major patching. Yield every API level from the maximum down to the\n    # minimum, inclusive.\n    min_api_level = 16\n    for ver in range(api_level, min_api_level - 1, -1):\n        yield f\"android_{ver}_{abi}\"","sourceCodeStart":727,"sourceCodeEnd":763,"githubUrl":"https://github.com/pypa/pip/blob/d7d0d0a39494e28ec1c407bd0680e4a4d1067791/src/pip/_vendor/packaging/tags.py#L727-L763","documentation":"Raised by `android_platforms(api_level, abi)` in `packaging.tags` when the host is not Android (i.e. `platform.system() != 'Android'`) and either `api_level` or `abi` is `None`. On Android, the defaults are inferred from `platform.android_ver()` and `sysconfig.get_platform()`; off-Android there is no such host state to infer, so both arguments must be supplied explicitly to produce valid Android platform tags like `android_33_arm64_v8a`.","triggerScenarios":"Calling `android_platforms()` (or a code path that feeds it, such as a cross-compiling resolver) on Linux/macOS/Windows without passing both `api_level` and `abi`. The guard is `platform.system() != 'Android' and (api_level is None or abi is None)`.","commonSituations":"Cross-building wheels for Android from a desktop CI runner; migrating from a docs example that omitted the args; assuming defaults work everywhere; running tests for an Android-packaging tool on a developer laptop.","solutions":["Pass both arguments explicitly: `android_platforms(api_level=33, abi='arm64_v8a')`.","Parametrize the Android API level and ABI from your build config / target NDK settings rather than relying on host defaults.","Guard the call site so `android_platforms()` is only invoked when actually targeting Android.","If on Android but still hitting it, upgrade to Python 3.13+ where `platform.system() == 'Android'` and `platform.android_ver()` exist."],"exampleFix":"// before\nfrom pip._vendor.packaging.tags import android_platforms\nplats = list(android_platforms())  # raises on desktop\n\n# after\nfrom pip._vendor.packaging.tags import android_platforms\nplats = list(android_platforms(api_level=33, abi='arm64_v8a'))","handlingStrategy":"validation","validationCode":"import platform\n\ndef android_platforms_safe(api_level=None, abi=None):\n    if platform.system() != 'Android' and (api_level is None or abi is None):\n        raise ValueError('api_level and abi are required when not running on Android')\n    from pip._vendor.packaging.tags import android_platforms\n    return list(android_platforms(api_level=api_level, abi=abi))","typeGuard":null,"tryCatchPattern":"from pip._vendor.packaging.tags import android_platforms\n\ntry:\n    plats = list(android_platforms(api_level=api_level, abi=abi))\nexcept TypeError as e:\n    if 'api_level and abi' in str(e):\n        raise ValueError('Provide api_level and abi when targeting Android off-device') from e\n    raise","preventionTips":["Always pass `api_level` and `abi` explicitly when cross-targeting Android.","Source both values from your NDK/build config, not the host.","Guard the call site so Android tag generation only runs when targeting Android."],"tags":["python","packaging","tags","android","cross-compilation","arguments"],"analyzedSha":"d7d0d0a39494e28ec1c407bd0680e4a4d1067791","analyzedAt":"2026-08-04T20:55:04.259Z","schemaVersion":2}