Skip to content

WHIZ120: Pinned Type Renamed Without Ledger Acknowledgment

Verified by tests

PinnedTypeRenameAnalyzerTests — library CI run #31657041675 (2026-08-13)

Severity: Error Category: Identity / Type Rename

Description

A type carrying [PinnedId] has a CLR name that is neither the name recorded in the committed pinned-type ledger for its pinned id nor one of that entry's formerNames. In other words, the type was renamed, and the rename has not been acknowledged.

This matters because messages are stored in the append-only event log under the name of the day. If the running code no longer knows the old name, every event stored under it becomes unreadable. WHIZ120 fails the build so the rename is recorded — as a former-name alias — before it can silently break stored-event deserialization.

The analyzer is inert when no ledger is present, so this diagnostic only fires once a project has adopted the ledger.

Diagnostic Message

Pinned type '{SimpleName}' (id {PinnedId}) has CLR name '{CurrentName}' but the pinned-type ledger records
'{LedgerName}'. This is a rename: in .whizbang/pinned-type-ledger.json, add '{LedgerName}' to this entry's
formerNames and set its clrTypeName to '{CurrentName}' so old stored events still resolve to this type.

Common Causes

  1. Renaming an event, command, or perspective type without updating the ledger.
  2. Moving a type to a different namespace (the CLR name includes the namespace).
  3. Nesting or un-nesting a type (nested types use + in the CLR name).

How to Fix

In .whizbang/pinned-type-ledger.json, find the entry for the reported pinned id and:

  1. Add the ledger's currently-recorded name to that entry's formerNames.
  2. Set the entry's clrTypeName to the new (current) name.
{
  "pinnedId": "11111111-2222-3333-4444-555555555555",
  "clrTypeName": "MyApp.Contracts.OrderPlacedEvent",
  "kind": "event",
  "formerNames": ["MyApp.Contracts.OrderCreatedEvent"]
}

Rebuild. WHIZ120 clears, and MessageJsonContextGenerator now emits an alias so events stored under the former name still deserialize to the current type. Commit the ledger change alongside the rename — the diff is the acknowledgment.

The VSCode extension can apply this edit inline.

When It Is Intentional

If you are genuinely retiring a pinned id (not renaming), remove the type and prune its ledger entry — see WHIZ121. Renaming is not the same as replacing: to replace a type, create a new type with a new [PinnedId].