unionlabs/union · error · Error

No return value from compute_salt

Error message

No return value from compute_salt

What it means

compute_salt reads a Move function via the same dev-inspect wrapper (moveCall on package 0x835e…779 executed with devInspectTransactionBlock) and requires result[0].returnValues[0] to hold the returned vector<u8>; the caller then strips the BCS length prefix (slice(1)) and hex-encodes it. An aborted simulation or unexpected result shape leaves returnValues empty and triggers this throw.

Source

Thrown at ts-sdk/src/sui/quote-token.ts:50

    const function_arguments = [
      tx.pure.u256(0),
      tx.pure.u32(config.channelId),
      tx.pure("vector<u8>", hexToBytes(converted_base_token)),
    ]

    const result = yield* readContract(
      client,
      "0x835e6a7d0e415c0f1791ae61241f59e1dd9d669d59369cd056f02b3275f68779",
      contract_address,
      module_id,
      function_name,
      [],
      function_arguments,
      tx,
    )

    if (!result || result.length === 0 || !result[0].returnValues || !result[0].returnValues[0]) {
      throw new Error("No return value from compute_salt")
    }
    const [rawBytes /*, _typeTag*/] = result[0].returnValues[0] as [number[], string]

    return bytesToHex(rawBytes.slice(1))
  })

View on GitHub (pinned to 031785bb6d)

Solutions

  1. Confirm the module/function still exist with the expected signature on package 0x835e…779 for your network
  2. Check the argument encoding and order against the Move source before calling
  3. Handle the defect explicitly (Effect.catchDefect) and surface the dev-inspect status/error for diagnosis

Example fix

// before
if (!result || result.length === 0 || !result[0].returnValues || !result[0].returnValues[0]) {
  throw new Error("No return value from compute_salt")
}

// after
const r = result?.[0]
const status = (r as { status?: { status?: string; error?: string } })?.status
if (status?.status === "failure") {
  throw new Error(`compute_salt aborted: ${status.error ?? "unknown Move abort"}`)
}
if (!r?.returnValues?.[0]) {
  throw new Error("No return value from compute_salt")
}
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm the target module/function exist on the package before the read
const pkg = await client.getObject({ id: packageId })
if (pkg.data?.content?.dataType !== "package") {
  throw new Error(`Package ${packageId} not found on this network`)
}

Type guard

const hasReturnValue = (
  r: { returnValues?: unknown[][] } | undefined,
): r is { returnValues: [unknown[], ...unknown[][]] } =>
  Array.isArray(r?.returnValues) && r.returnValues.length > 0 && Array.isArray(r.returnValues[0])

Try / catch

import { Effect, Exit } from "effect"

const exit = await Effect.runPromiseExit(
  program.pipe(Effect.catchDefect(e => Effect.fail(e))),
)
if (Exit.isFailure(exit)) {
  // check argument order/encoding and the current compute_salt signature
}

Prevention

When it happens

Trigger: Wrong or mis-ordered function_arguments (the salt inputs, e.g. chain/counterparty addresses) causing the Move entry to abort; module_id/function_name drift after a contract upgrade; network mismatch between client and the hardcoded package address.

Common situations: Contract upgrades changing the compute_salt signature while the SDK pins the old one; testnet addresses used against mainnet.

Related errors


AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16). Data as JSON: /api/errors/f9adbf8589ac25a5. Report an issue: GitHub.