MuntashirAkon/AppManager · error · JSONException

Empty JSON string.

Error message

Empty JSON string.

What it means

readLogFile reads the OAndBackup `<package>.log` file and parses it as JSON. If the file content is empty or whitespace-only, it throws JSONException("Empty JSON string.") which propagates as a BackupException. The log file must contain a valid JSON object with label/packageName/versionName/versionCode.

Solutions

  1. Check the <package>.log file size and content — re-create the OAndBackup backup if it is empty
  2. Ensure you are converting the correct backup directory containing a complete log file
  3. Re-run the original OAndBackup backup, then convert again

Example fix

// caller-side guard
String json = logFile.getContentAsString();
if (json == null || json.trim().isEmpty()) {
    // skip this package; do not call convert()
    return;
}
converter.convert();
Defensive patterns

Strategy: validation

Validate before calling

Path logFile = backupLocation.findFile(packageName + ".log");
String s = logFile.getContentAsString();
if (s == null || s.trim().isEmpty()) {
    throw new IllegalStateException("OAB log empty for " + packageName + "; re-create backup");
}

Type guard

static boolean isValidOabLog(String s) {
    if (s == null || s.trim().isEmpty()) return false;
    try {
        JSONObject o = new JSONObject(s);
        return o.has("label") && o.has("packageName") && o.has("versionName") && o.has("versionCode");
    } catch (JSONException e) { return false; }
}

Try / catch

try {
    converter.convert();
} catch (JSONException | BackupException e) {
    if ("Empty JSON string.".equals(e.getMessage())) {
        // skip this package or re-run the original OAndBackup backup
    }
}

Prevention

When it happens

Trigger: mBackupLocation.findFile(mPackageName + ".log") returns a 0-byte (or blank) file — the OAndBackup log was never written, was truncated, or points at the wrong file.

Common situations: Interrupted OAndBackup run left an empty log; user copied backup folders partially; wrong package directory selected for conversion.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java:190

    }

    @Override
    public void cleanup() {
        mSourceCrypto.close();
        mBackupLocation.delete();
    }

    @Override
    public String getPackageName() {
        return mPackageName;
    }

    private BackupMetadataV2 readLogFile() throws BackupException {
        try {
            BackupMetadataV2 metadataV2 = new BackupMetadataV2();
            Path logFile = mBackupLocation.findFile(mPackageName + ".log");
            String jsonString = logFile.getContentAsString();
            if (TextUtils.isEmpty(jsonString)) throw new JSONException("Empty JSON string.");
            JSONObject jsonObject = new JSONObject(jsonString);
            metadataV2.label = jsonObject.getString("label");
            metadataV2.packageName = jsonObject.getString("packageName");
            metadataV2.versionName = jsonObject.getString("versionName");
            metadataV2.versionCode = jsonObject.getInt("versionCode");
            metadataV2.isSystem = jsonObject.optBoolean("isSystem");
            metadataV2.isSplitApk = false;
            metadataV2.splitConfigs = ArrayUtils.emptyArray(String.class);
            metadataV2.hasRules = false;
            metadataV2.backupTime = jsonObject.getLong("lastBackupMillis");
            metadataV2.crypto = jsonObject.optBoolean("isEncrypted") ? CryptoUtils.MODE_OPEN_PGP : CryptoUtils.MODE_NO_ENCRYPTION;
            mSourceCryptoMode = metadataV2.crypto;
            mSourceCrypto = CryptoUtils.setupCrypto(metadataV2);
            metadataV2.apkName = new File(jsonObject.getString("sourceDir")).getName();
            // Flags
            metadataV2.flags = new BackupFlags(BackupFlags.BACKUP_MULTIPLE);
            int backupMode = jsonObject.optInt("backupMode", MODE_UNSET);
            if (backupMode == MODE_UNSET) {

View on GitHub (pinned to 0152f468fc)