Tencent/tinker · error · TinkerRuntimeException

tinkerLoadVerifyFlag must not be null.

Error message

tinkerLoadVerifyFlag must not be null.

What it means

Tinker.Builder.tinkerLoadVerifyFlag(Boolean) throws TinkerRuntimeException("tinkerLoadVerifyFlag must not be null.") when passed a null Boolean. The flag controls whether patch files are md5-verified at load time, so it must be a definite true/false decision; the builder distinguishes 'not yet set' (null field) from 'set' and requires an explicit value, rejecting null arguments including Boolean variables that were never assigned.

Solutions

  1. Default the value explicitly before the call: Boolean verify = (cfgFlag != null) ? cfgFlag : Boolean.FALSE; then pass it.
  2. If the source is BuildConfig, define the field in every flavor or use a constant.
  3. Log the resolved value during init to catch null sources early in QA builds.

Example fix

// before
Boolean verify = configMap.get("verifyPatchOnLoad"); // null when key missing
builder.tinkerLoadVerifyFlag(verify); // throws

// after
Boolean raw = configMap.get("verifyPatchOnLoad");
builder.tinkerLoadVerifyFlag(raw != null ? raw : Boolean.FALSE);
Defensive patterns

Strategy: validation

Validate before calling

Boolean raw = config.get("tinkerLoadVerifyFlag");
boolean verify = (raw != null) ? raw : false; // explicit default
builder.tinkerLoadVerifyFlag(verify);

Prevention

When it happens

Trigger: Calling tinkerLoadVerifyFlag(null) — typically a Boolean read from a config map, BuildConfig field, or intent extra that is absent in the current build/variant, or a boxed variable defaulted to null.

Common situations: Reading the flag from a JSON/config file where the key is missing in some environments; flavor-specific BuildConfig fields not defined in all variants; deserialized preferences returning null after a schema change.

Related errors


AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14). Data as JSON: /api/errors/050db629f1828a24. Report an issue: GitHub.

Appendix: source

Thrown at tinker-android/tinker-android-lib-no-op/src/main/java/com/tencent/tinker/lib/tinker/Tinker.java:324

                ShareTinkerLog.e(TAG, "patchDirectory is null!");
                return;
            }
            this.patchInfoFile = SharePatchFileUtil.getPatchInfoFile(patchDirectory.getAbsolutePath());
            this.patchInfoLockFile = SharePatchFileUtil.getPatchInfoLockFile(patchDirectory.getAbsolutePath());
            ShareTinkerLog.w(TAG, "tinker patch directory: %s", patchDirectory);
        }

        public Builder tinkerFlags(int tinkerFlags) {
            if (this.status != -1) {
                throw new TinkerRuntimeException("tinkerFlag is already set.");
            }
            this.status = tinkerFlags;
            return this;
        }

        public Builder tinkerLoadVerifyFlag(Boolean verifyMd5WhenLoad) {
            if (verifyMd5WhenLoad == null) {
                throw new TinkerRuntimeException("tinkerLoadVerifyFlag must not be null.");
            }
            if (this.tinkerLoadVerifyFlag != null) {
                throw new TinkerRuntimeException("tinkerLoadVerifyFlag is already set.");
            }
            this.tinkerLoadVerifyFlag = verifyMd5WhenLoad;
            return this;
        }

        public Builder loadReport(LoadReporter loadReporter) {
            if (loadReporter == null) {
                throw new TinkerRuntimeException("loadReporter must not be null.");
            }
            if (this.loadReporter != null) {
                throw new TinkerRuntimeException("loadReporter is already set.");
            }
            this.loadReporter = loadReporter;
            return this;
        }

View on GitHub (pinned to 1b7ea02c23)