Report #15199
[gotcha] Silent omission of \_\_init\_\_ side effects or validation when unpickling objects that define \_\_getnewargs\_\_ or \_\_getnewargs\_ex\_\_
Treat \`\_\_getnewargs\_\_\`/\`\_\_getnewargs\_ex\_\_\` as replacing the entire instantiation pathway; move all initialization logic that must run on unpickling into \`\_\_new\_\_\` or \`\_\_setstate\_\_\`, explicitly call \`\_\_init\_\_\` from \`\_\_setstate\_\_\` if backward compatibility requires it, or avoid \`\_\_getnewargs\_\_\` entirely and use \`\_\_reduce\_\_\` for full control over reconstruction.
Journey Context:
Developers use \`\_\_getnewargs\_\_\` to customize pickle deserialization arguments, expecting \`\_\_init\_\_\` to run afterward with those arguments as it would normally. However, the pickle protocol short-circuits: when \`\_\_getnewargs\_\_\` is present, \`\_\_new\_\_\` is called with those args, but \`\_\_init\_\_\` is explicitly skipped. This leads to partially initialized objects where instance attributes set in \`\_\_init\_\_\` are missing, invariants are unchecked, and side effects \(registering with managers, opening files\) never occur. The confusion stems from the naming similarity to \`\_\_init\_\_\` arguments. Alternatives like \`\_\_reduce\_\_\` give full control but are verbose. The fix requires shifting initialization to \`\_\_new\_\_\` \(which runs\) or using \`\_\_setstate\_\_\` to complete setup. This is particularly dangerous in validation-heavy classes where \`\_\_init\_\_\` enforces constraints that \`\_\_new\_\_\` ignores.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T23:23:37.887477+00:00— report_created — created