Tencent/tinker · error · TinkerRuntimeException
tinkerLoadVerifyFlag is already set.
Error message
tinkerLoadVerifyFlag is already set.
What it means
Builder.tinkerLoadVerifyFlag may only be called once, same policy as the other builder setters: the stored Boolean is used both as the value and as the 'already set' marker, so a second call throws instead of silently overwriting the first configuration.
Source
Thrown at tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/Tinker.java:378
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;
}
public Builder patchReporter(PatchReporter patchReporter) {
if (patchReporter == null) {View on GitHub (pinned to 1b7ea02c23)
Solutions
- Set the flag once, at a single configuration site owned by the app module.
- If layered configuration is needed, compute the final boolean first and call the setter once.
- Instantiate a new Builder for each independent configuration (e.g., per test).
Example fix
// before builder.tinkerLoadVerifyFlag(true); // base init builder.tinkerLoadVerifyFlag(false); // app override -> throws // after boolean verify = flavor == Release ? true : false; builder.tinkerLoadVerifyFlag(verify); // single call
Defensive patterns
Strategy: validation
Validate before calling
boolean verify = flavor == ReleaseFlavor || serverConfig.forceVerify; builder.tinkerLoadVerifyFlag(verify); // exactly one call, computed beforehand
Prevention
- Decide the load-verify value at a single configuration site before building.
- Prevent helper libraries from calling builder setters the app already set.
- Reuse of a Builder across multiple builds (e.g., tests) is unsafe; construct a fresh one.
When it happens
Trigger: Calling tinkerLoadVerifyFlag(...) twice on the same Builder — e.g., a shared init helper sets it, then the app's own setup sets it again with a different value.
Common situations: Library and app both configuring tinker; copy-pasted config blocks; a builder field reused across multiple init attempts in tests.
Related errors
- tinkerFlag is already set.
- tinkerFlag is already set.
- tinkerLoadVerifyFlag must not be null.
- tinkerLoadVerifyFlag is already set.
- loadReporter is already set.
AI-assisted analysis of Tencent/tinker@1b7ea02c23 (2026-08-14).
Data as JSON: /api/errors/f0436f250d0b3eb7.
Report an issue: GitHub.