## TL;DR

Durable Object IDs are namespaced to their class binding. An ID minted for one class (or parsed from a string belonging to another namespace) cannot be used with a different namespace binding. Always derive IDs from the same binding you call get on, and never persist raw ID strings across a class rename.

## The query

```text
workerd error: 'Durable Object ID is not valid for this namespace'
```

## Use this when

- `idFromString` throws naming the namespace.
- The code passes IDs between two different DO classes.
- A class was renamed or split and old stored IDs are reused.

## Not for

- 'Durable Object ID from string is invalid' (malformed string, separate fix).
- The DO binding undefined at runtime (binding config problem).
- Storage or alarm failures inside the DO.

## Steps

### Step 1: Find where the ID string came from

Trace the string back to its minting: which binding's `idFromName` or unique-id call created it.

Expected result: the ID was minted under a different class binding than the one calling get. That mismatch is the entire bug.

### Step 2: Derive and use IDs from one binding

```js
const id = env.CHAT_ROOM.idFromName(roomName);
const stub = env.CHAT_ROOM.get(id);
```

Expected result: minting and use share the binding. The namespace always matches.

### Step 3: Audit stored ID strings

If IDs are persisted (in D1, KV, URLs), record which class minted each one. After a class rename or split, old strings are invalid under the new binding.

Expected result: a migration maps old IDs to new ones, or the code keeps the old binding name for compatibility.

### Step 4: Never swap bindings under an ID

Refactors that rename the binding in wrangler.toml invalidate every stored ID string for that class.

Expected result: binding renames are treated as data migrations, not config tweaks.

### Step 5: Verify the round trip

Mint an ID, stringify it, parse it back with the same binding, and get the stub.

Expected result: no namespace error. The full cycle works before the code ships.

## Why it happens

The ID string embeds the namespace it belongs to. This is a safety feature: it stops you from addressing the wrong class's objects. But it means IDs are not portable across classes, and any code that treats them as opaque tokens and passes them between bindings breaks.

## Edge cases

- `idFromName` is deterministic per namespace and name pair. The same name under two classes yields two different, incompatible IDs.
- Jurisdiction or location-hint parameters do not change the namespace; only the class binding does.
- Preview and production share ID formats but behave as separate namespaces in practice; do not copy production ID strings into preview tests.
- Keep one helper that mints IDs per class so call sites cannot mix bindings by accident.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_sIXvhKFduATXqdqU6H0m-A
