clockworklabs/SpacetimeDB · error

data key not found in return object

Error message

data key not found in return object

What it means

For ABI-v2 view calls the host expects __call_view_anon__ to return an object with a `data` field containing a Uint8Array of encoded rows. This error means the object came back without a readable `data` property — an envelope-shape mismatch between the module's v2 bindings and the host's protocol. The view may have run fine; its result simply cannot be decoded.

Source

Thrown at crates/core/src/host/v8/syscall/v2.rs:556

        args: view_args,
    } = op;
    // Serialize the arguments.
    let view_id = serialize_to_js(scope, &view_id)?;
    let sender = serialize_to_js(scope, &sender.to_u256())?;
    let view_args = serialize_to_js(scope, view_args.get_bsatn())?;
    let args = &[view_id, sender, view_args];

    // Call the function.
    let ret = call_recv_fun(scope, fun, hooks.recv, args)?;

    // Returns an object with a `data` field containing the bytes.
    let ret = cast!(scope, ret, v8::Object, "object return from `__call_view_anon__`").map_err(|e| e.throw(scope))?;

    let Some(data_key) = v8::String::new(scope, "data") else {
        return Err(ErrorOrException::Err(anyhow::anyhow!("error creating a v8 string")));
    };
    let Some(data_val) = ret.get(scope, data_key.into()) else {
        return Err(ErrorOrException::Err(anyhow::anyhow!(
            "data key not found in return object"
        )));
    };

    let ret = cast!(
        scope,
        data_val,
        v8::Uint8Array,
        "bytes in the `data` field returned from `__call_view_anon__`"
    )
    .map_err(|e| e.throw(scope))?;
    let bytes = ret.get_contents(&mut []);

    Ok(ViewReturnData::HeaderFirst(Bytes::copy_from_slice(bytes)))
}

/// Calls the `__call_view_anon__` function `fun`.
pub(super) fn call_call_view_anon(

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Regenerate the JS bindings for the deployed host/ABI version and republish the module.
  2. Keep the returned envelope exactly `{ data: Uint8Array }` in any custom wrapper.
  3. Verify the deployed bundle actually contains the regenerated wrapper (bust caches).
  4. Pin host and bindings versions together in CI so they cannot drift.

Example fix

// before: v2 wrapper returns rows under a different key
return { rows: encoded };

// after: v2 envelope with the `data` field
return { data: encoded };
Defensive patterns

Strategy: validation

Validate before calling

// v2 envelope check in bindings tests
const out = await callViewAnon(viewId, args);
if (!(out && out.data instanceof Uint8Array)) {
    throw new Error('v2 view call must return { data: Uint8Array }');
}

Type guard

function isV2ViewEnvelope(v: unknown): v is { data: Uint8Array } {
  return typeof v === 'object' && v !== null && (v as any).data instanceof Uint8Array;
}

Prevention

When it happens

Trigger: The v2 view wrapper returns an object lacking `data`: bindings generated for a different ABI or host version than deployed, a custom override of __call_view_anon__ returning a different envelope, or mixed old/new bundle code after an upgrade.

Common situations: Upgrading the host without regenerating JS bindings; forking or wrapping generated view entry points; serving stale bundles from caches after a republish.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/4affd07c9b1c26e9. Report an issue: GitHub.