Errors
Error types the New Theory inference API emits, grouped by WebSocket close code.
Every abnormal WebSocket close includes a JSON payload (the error envelope) with six fields.
{
"code": 4001,
"type": "auth.invalid_key",
"message": "API key rejected. The key was revoked, never issued, or malformed. Generate a new key in the New Theory console.",
"context": { "key_prefix": "nt_a1b2c3d4" },
"docs": "https://docs.newtheory.ai/api/errors",
"trace_id": "tr_a1b2c3d4"
}| Field | Type | Notes |
|---|---|---|
code | integer | WebSocket close code. One of 4001, 4403, 4400, 4404, 4422, 4500, 4503. |
type | string | Dot-namespaced subtype (domain.specific). Stable identifier for programmatic handling. |
message | string | Human-readable description. Do not parse; use type for branching. |
context | object | Structured diagnostics. Fields vary by type — see each entry below. |
docs | string (URI) | Link to this page's anchor for the error type. |
trace_id | string | Opaque support token (tr_xxxxxxxx). Include in support requests. |
In the Python SDK, every close triggers an exception that inherits from newt.NewTheoryError. Catch by class for domain-level handling, branch on exc.type for specific cases.
import newt
try:
robot.run("pick up the cup")
except newt.AuthError as e:
print(e.type, e.trace_id) # "auth.invalid_key", "tr_a1b2c3d4"
except newt.NewTheoryError as e:
print(e.code, e.type, e.message)Every error the server can emit is registered in a single-source catalog, and server startup validates coverage — a new error type can't ship without an entry.
Raised before connection
These conditions are detected by the SDK during Robot() construction, before any WebSocket is opened.
RegistryUnavailable
The registry service (nt-registry-production.up.railway.app) was unreachable when Robot() tried to resolve the model and contract. This is the only condition that raises RegistryUnavailable — it means the registry itself is down or the host cannot reach it, not a model or auth problem.
Next step: check your network, verify NT_BOOTSTRAP_URL is not set to a bad value (leave it unset to use the production registry), and retry. If the registry is down, wait and retry — it is an always-on service and outages are brief.
AuthError at construction
Your API key failed validation at the registry during Robot() construction — the registry returned a 401 with a hint that valid keys start with nt_. The connection closes before any WebSocket is opened.
Next step: re-export NT_API_KEY with the correct key (nt_ prefix + 40 hex chars), or generate a new key in the console.
ColdStartRetry warning
Not an error — a logging.WARNING the SDK emits when the GPU container did not respond within the initial connection timeout and the SDK is opening an extended retry (180s). This is the normal cold-start signal. Wait it out; a cold container can take a few minutes to come up. If the extended retry also times out, a TimeoutError is raised to your code.
4001 — Authentication
Sent when the API key fails verification at the WebSocket handshake. The connection closes before any inference runs.
auth.invalid_key
SDK exception: newt.AuthError
The submitted key was revoked, never issued, or malformed.
{
"code": 4001,
"type": "auth.invalid_key",
"message": "API key rejected. The key was revoked, never issued, or malformed. Generate a new key in the New Theory console.",
"context": {
"key_prefix": "nt_a1b2c3d4"
},
"trace_id": "tr_a1b2c3d4"
}context.key_prefix is the first eight characters of the submitted key — enough for diagnostics without leaking the full value.
Next step: generate a new key in the console. If the key was just created, confirm it has not been revoked.
4403 — Authorization
Sent when the API key is valid but does not own the requested model. A fine-tune belongs to the team that made it — another team's key can't serve it. The connection closes before any inference runs.
auth.forbidden
SDK exception: newt.ForbiddenError
{
"code": 4403,
"type": "auth.forbidden",
"message": "That model belongs to another team. Your key can only serve models your team owns.",
"context": {
"model": "ft_6341c5_d13da9"
},
"trace_id": "tr_a1b2c3d4"
}context.model is the requested model identifier, as submitted.
Next step: use one of your own team's models, or ask the owning team to share. A model's owner is the team that fine-tuned it.
4400 — Protocol
Sent when a received frame cannot be decoded or is structurally invalid. The connection closes on the first bad frame. The Python SDK raises newt.ProtocolError for all 4400 subtypes.
protocol.malformed_msgpack
SDK exception: newt.ProtocolError
A binary WebSocket frame could not be decoded as msgpack.
{
"code": 4400,
"type": "protocol.malformed_msgpack",
"message": "The server received a WebSocket frame that could not be decoded as msgpack. Ensure every frame is msgpack-encoded binary.",
"context": {
"frame_bytes": 42
},
"trace_id": "tr_a1b2c3d4"
}context.frame_bytes is the size of the frame that failed to decode.
Next step: use msgpack.packb(obs, use_bin_type=True) to encode each frame. Text WebSocket frames are not accepted.
protocol.missing_type
SDK exception: newt.ProtocolError
A decoded msgpack frame did not contain the required type key.
{
"code": 4400,
"type": "protocol.missing_type",
"message": "The server received a msgpack frame with no 'type' key. Every frame must include a 'type' key set to 'obs' or 'stop'.",
"context": {
"keys_present": ["state", "images"]
},
"trace_id": "tr_a1b2c3d4"
}context.keys_present lists the keys the server found in the frame.
Next step: ensure every frame dict includes a "type" key before packing.
protocol.unknown_type
SDK exception: newt.ProtocolError
A decoded msgpack frame had a type value the server does not recognize.
{
"code": 4400,
"type": "protocol.unknown_type",
"message": "The server received a frame with an unrecognized type. Accepted frame types are: 'obs', 'stop'.",
"context": {
"received_type": "observation"
},
"trace_id": "tr_a1b2c3d4"
}context.received_type is the value the server received.
Next step: type must be exactly "obs" (to send an observation) or "stop" (to end the session).
4404 — Model not found
Sent when the model identifier in the first obs frame does not match any UID or tag in the server's registry.
model_not_found.unknown_identifier
SDK exception: newt.ModelNotFoundError
{
"code": 4404,
"type": "model_not_found.unknown_identifier",
"message": "Model not found. Check spelling or call newt.list_models() to see available models.",
"context": {
"requested": "so101-v2",
"known_uids": ["ft_base_molmoact2", "ft_6341c5_d13da9"],
"known_tags": ["so101"]
},
"trace_id": "tr_a1b2c3d4"
}context.requested is the identifier from the obs frame. context.known_uids and context.known_tags list what the registry contained at the time.
Next step: model identifiers are case-sensitive. Run newt.list_models() to see current UIDs and tags.
4422 — Contract mismatch
Sent when an obs frame's data does not match the model's trained input contract. Each subtype names the specific field that failed validation. The Python SDK raises newt.ContractMismatchError for all 4422 subtypes.
contract_mismatch.state_shape
SDK exception: newt.ContractMismatchError
The state array shape does not match the shape the model was trained on.
{
"code": 4422,
"type": "contract_mismatch.state_shape",
"message": "State shape mismatch. Adjust read_state() to return the expected shape, or switch to a model that matches your robot.",
"context": {
"model": "so101",
"expected_shape": [6],
"got_shape": [14]
},
"trace_id": "tr_a1b2c3d4"
}Next step: check the model's expected state shape via robot.contract. The contract is fixed at training time.
contract_mismatch.state_dtype
SDK exception: newt.ContractMismatchError
The state array dtype does not match the dtype the model was trained on.
{
"code": 4422,
"type": "contract_mismatch.state_dtype",
"message": "State dtype mismatch. Cast your state array to the expected dtype in read_state().",
"context": {
"model": "so101",
"expected_dtype": "float32",
"got_dtype": "float64"
},
"trace_id": "tr_a1b2c3d4"
}Next step: most models expect float32. Use state.astype(np.float32) in read_state().
contract_mismatch.camera_missing
SDK exception: newt.ContractMismatchError
A camera the model requires was absent from the obs frame's images dict.
{
"code": 4422,
"type": "contract_mismatch.camera_missing",
"message": "Required camera missing. Add the missing camera to the images dict in read_state(), or switch to a model that matches your hardware.",
"context": {
"model": "so101",
"missing_required_camera": "side",
"cameras_required": ["top", "side"],
"got_cameras": ["top"]
},
"trace_id": "tr_a1b2c3d4"
}context.missing_required_camera names the absent key. context.cameras_required lists all keys the model requires.
Next step: check cameras.required via robot.contract. Each required camera key must appear in the images dict.
contract_mismatch.image_shape
SDK exception: newt.ContractMismatchError
A camera image's shape does not match the shape the model expects.
{
"code": 4422,
"type": "contract_mismatch.image_shape",
"message": "Image shape mismatch. Resize the camera frame to the expected shape (CHW) in read_state().",
"context": {
"model": "so101",
"camera": "top",
"expected_shape": [3, 224, 224],
"got_shape": [3, 480, 640]
},
"trace_id": "tr_a1b2c3d4"
}Next step: images must be in CHW layout. Check the expected shape via robot.contract and resize on the client.
4500 — Server error
Sent when the server encounters an unhandled exception, either inside the model call or in the WebSocket handler itself. The Python SDK raises newt.ServerError for all 4500 subtypes. Include exc.trace_id in any support request.
server.inference_error
SDK exception: newt.ServerError
The model raised an unhandled exception during policy.infer().
{
"code": 4500,
"type": "server.inference_error",
"message": "The model raised an error during inference. Retry the request. If this persists, contact support with the trace_id.",
"context": {
"error_type": "RuntimeError"
},
"trace_id": "tr_a1b2c3d4"
}context.error_type is the Python exception class name from the inference call.
Next step: retry the request. If this persists, contact support with the trace_id. This error may indicate an edge case in the input data.
In an earlier protocol revision, in-model errors emitted a terminal frame with stop_reason="error" and closed with code 1000. They now close 4500 with this envelope, so ServerError is raised rather than returning a RunResult with stop_reason="error".
server.internal
SDK exception: newt.ServerError
An unhandled exception occurred in the WebSocket handler outside the inference path.
{
"code": 4500,
"type": "server.internal",
"message": "The server encountered an internal error and closed the session. Retry the request. If this persists, contact support with the trace_id.",
"context": {
"error_type": "ValueError"
},
"trace_id": "tr_a1b2c3d4"
}Next step: retry the request. If this persists, contact support with the trace_id.
Embodiment
Raised by the SDK during Robot() construction when the value passed to embodiment= is invalid. This is a client-side check — no WebSocket is opened, and no server is involved. The SDK raises newt.EmbodimentError for all three subtypes; the code is 4422 by HTTP convention. See the SDK reference for the protocol an embodiment object must satisfy.
embodiment.string_not_object
SDK exception: newt.EmbodimentError
Raised when embodiment= receives a string. embodiment= takes your embodiment object, not a name string — the SDK never resolves names. This commonly happens when a developer expects a name-based API such as Robot(embodiment="so101").
{
"code": 4422,
"type": "embodiment.string_not_object",
"message": "Robot(embodiment=) takes your embodiment object, not a name string (got 'so101'). Generate one with a starter kit, or implement read_state() and execute() on any class.",
"context": { "got": "so101" }
}context.got is the string the SDK received.
Next step: pass an object that implements read_state() and execute(). Generate one with a starter kit, or write your own class — see Set up your embodiment.
embodiment.conflict
SDK exception: newt.EmbodimentError
Raised when embodiment= is combined with read_state= or execute=. The two paths are equivalent and mutually exclusive: embodiment= is convenience shorthand for passing the two callbacks separately.
{
"code": 4422,
"type": "embodiment.conflict",
"message": "Robot() received both embodiment= and read_state=. Pick one path: pass embodiment= (an object with read_state() and execute()), or pass read_state= and execute= as separate callbacks. The two paths are equivalent; embodiment= is convenience shorthand.",
"context": { "conflict_kwargs": ["read_state="] }
}context.conflict_kwargs lists the conflicting callback arguments the SDK saw.
Next step: pass embodiment= alone, or pass read_state= and execute= alone. Not both.
embodiment.missing_method
SDK exception: newt.EmbodimentError
Raised when the object passed as embodiment= is missing read_state(), execute(), or both. The message names every missing method.
{
"code": 4422,
"type": "embodiment.missing_method",
"message": "The object passed as embodiment= is missing: execute(). An embodiment must implement both read_state() -> dict and execute(action_chunk) -> None.",
"context": { "missing": ["execute()"], "got_type": "PartialRig" }
}context.missing lists the absent methods; context.got_type is the class name of the object that was passed.
Next step: implement both read_state() -> dict and execute(action_chunk) -> None on the class. Any object with those two methods is an embodiment — no inheritance or registration required.
4503 — Verifier unavailable
Sent when the key verification service is unreachable or returns an error during the WebSocket handshake. The connection closes before any inference runs.
verifier.unavailable
SDK exception: newt.VerifierError
{
"code": 4503,
"type": "verifier.unavailable",
"message": "The API key verification service is temporarily unavailable. Retry the request in a few seconds.",
"context": {
"error_type": "httpx.ConnectTimeout"
},
"trace_id": "tr_a1b2c3d4"
}context.error_type is the Python exception class from the verification call.
Next step: this is a server-side infrastructure issue, not a problem with your API key. Retry with exponential backoff.