{"record":{"id":"e3f91d8c58939ffe","repo":"unionlabs/union","slug":"error-while-incrementing-period-w","errorCode":null,"errorMessage":"error while incrementing period: %w","messagePattern":"error while incrementing period: %w","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"uniond/app/export.go","lineNumber":153,"sourceCode":"\t\t}\n\n\t\tif err := app.DistrKeeper.Hooks().AfterValidatorCreated(ctx, valBz); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\treturn false\n\t})\n\n\t// reinitialize all delegations\n\tfor _, del := range dels {\n\t\tvalAddr, err := sdk.ValAddressFromBech32(del.ValidatorAddress)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tdelAddr := sdk.MustAccAddressFromBech32(del.DelegatorAddress)\n\n\t\tif err := app.DistrKeeper.Hooks().BeforeDelegationCreated(ctx, delAddr, valAddr); err != nil {\n\t\t\t// never called as BeforeDelegationCreated always returns nil\n\t\t\tpanic(fmt.Errorf(\"error while incrementing period: %w\", err))\n\t\t}\n\n\t\tif err := app.DistrKeeper.Hooks().AfterDelegationModified(ctx, delAddr, valAddr); err != nil {\n\t\t\t// never called as AfterDelegationModified always returns nil\n\t\t\tpanic(fmt.Errorf(\"error while creating a new delegation period record: %w\", err))\n\t\t}\n\t}\n\n\t// reset context height\n\tctx = ctx.WithBlockHeight(height)\n\n\t/* Handle staking state. */\n\n\t// iterate through redelegations, reset creation height\n\terr = app.StakingKeeper.IterateRedelegations(ctx, func(_ int64, red stakingtypes.Redelegation) (stop bool) {\n\t\tfor i := range red.Entries {\n\t\t\tred.Entries[i].CreationHeight = 0\n\t\t}","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/unionlabs/union/blob/031785bb6dc6b957c624e62bc64c184409c97d7b/uniond/app/export.go#L135-L171","documentation":"During `uniond export` (genesis export for zero height), the app re-initializes every delegation by replaying the distribution module's BeforeDelegationCreated hook to rebuild validator periods — logic mirrored from cosmos-sdk's simapp export. The inline comment states the stock hook always returns nil, so this panic is a defensive assertion that only fires if the DistrKeeper's hooks start returning errors (fork or SDK drift).","triggerScenarios":"Running uniond export on a build where app.DistrKeeper.Hooks().BeforeDelegationCreated can return a non-nil error: a custom distribution keeper override adding validation, or a cosmos-sdk version upgrade that changes hook semantics.","commonSituations":"Forks that add error paths to distribution hooks; vendored cosmos-sdk version bumped without re-auditing export assumptions; test harnesses that inject failing hooks.","solutions":["Confirm you are running the stock uniond build — on stock builds this branch is unreachable","Inspect app.DistrKeeper.Hooks() (and any wrapping hook middleware) for overrides that can return errors","Align the cosmos-sdk version with the one union vendors, since hook signatures/behavior changed across SDK releases","If you maintain a fork whose hooks can fail, make them nil-safe for the export path or handle the error instead of panicking"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Exercise the export path on a disposable copy before relying on it\nuniond export --home /backup/union-snapshot --for-zero-height > /dev/null && echo export-ok","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pin the vendored cosmos-sdk version and review hook semantics on every bump","Avoid overriding distribution hooks in forks; if you must, keep them returning nil during export","Run uniond export regularly in CI against a fixture state so hook drift is caught early","Treat this panic as a signal your build's keeper behavior diverged from stock, not as data corruption"],"tags":["cosmos-sdk","genesis-export","distribution","panic","golang"],"backgroundTag":null,"analyzedSha":"031785bb6dc6b957c624e62bc64c184409c97d7b","analyzedAt":"2026-08-16T06:24:09.996Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}