MuntashirAkon/AppManager · error · JSONException

APK source is missing.

Error message

APK source is missing.

What it means

ApkQueueItem.validateForReplay() validates a queue item before replaying an installation. When the item is NOT an install-existing replay (mInstallExisting == false), mApkSource must point at the APK file(s) to install; if it is null the item has no APK to install and a JSONException is thrown.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/apk/installer/ApkQueueItem.java:235

        mTestOnly = jsonObject.optBoolean("test_only", false);
        mOriginatingPackage = JSONUtils.optString(jsonObject, "originating_package", null);
        String originatingUri = JSONUtils.optString(jsonObject, "originating_uri", null);
        mOriginatingUri = originatingUri != null ? Uri.parse(originatingUri) : null;
        JSONObject apkSource = jsonObject.optJSONObject("apk_source");
        mApkSource = apkSource != null ? ApkSource.DESERIALIZER.deserialize(apkSource) : null;
        JSONObject installerOptions = jsonObject.optJSONObject("installer_options");
        mInstallerOptions = installerOptions != null ? InstallerOptions.DESERIALIZER.deserialize(installerOptions) : null;
        mSelectedSplits = JSONUtils.getArray(jsonObject.optJSONArray("selected_splits"));
    }

    public void validateForReplay() throws JSONException {
        if (mInstallExisting) {
            if (TextUtils.isEmpty(mPackageName)) {
                throw new JSONException("Package name is missing.");
            }
        } else {
            if (mApkSource == null) {
                throw new JSONException("APK source is missing.");
            }
            if (mSelectedSplits == null || mSelectedSplits.isEmpty()) {
                throw new JSONException("Selected APK splits are missing.");
            }
        }
        if (mInstallerOptions != null) {
            setInstallerOptions(InstallerOptions.resolveEffectiveOptions(mInstallerOptions,
                    mPackageName, mTestOnly));
        }
    }

    @NonNull
    @Override
    public JSONObject serializeToJson() throws JSONException {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("op_id", mOperationId);
        jsonObject.put("package_name", mPackageName);
        jsonObject.put("app_label", mAppLabel);

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Ensure mApkSource (apk_source in the serialized JSON) is set before replaying the queue item
  2. If the intent is to reinstall an already-installed package, set mInstallExisting=true and provide mPackageName instead of an APK source
  3. Check that the original content/file URI permission still exists so the source is not lost between sessions
  4. Wrap getExecutableIntent/validateForReplay calls in try-catch for JSONException and surface a user-facing 'select an APK' prompt

Example fix

// before
JSONObject obj = new JSONObject(json);
ApkQueueItem item = new ApkQueueItem(obj); // apk_source missing
item.getExecutableIntent(context); // throws
// after
if (obj.optString("apk_source", null) == null && !obj.optBoolean("install_existing")) {
    obj.put("apk_source", pickedApkUri.toString());
}
ApkQueueItem item = new ApkQueueItem(obj);
item.getExecutableIntent(context);
Defensive patterns

Strategy: validation

Validate before calling

if (item.getApkSource() == null) { promptApkSelection(); }

Type guard

boolean hasSource(ApkQueueItem i) { return i.getApkSource() != null; }

Try / catch

try { item.getExecutableIntent(ctx); } catch (JSONException e) { log(e); }

When it happens

Trigger: Replaying an install queue item where mInstallExisting is false but mApkSource was never set — e.g. the item was created/deserialized from JSON without the apk_source field, or the source URI/file was dropped during persistence.

Common situations: Restoring a queued install from a saved JSON session where the apk_source key is absent; constructing an ApkQueueItem programmatically and forgetting to set the APK source; a cleared/revoked content-URI permission causing the source to be discarded.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/e9a302cd5298cd05. Report an issue: GitHub.