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
- Confirm the module/function still exist with the expected signature on package 0x835e…779 for your network
- Check the argument encoding and order against the Move source before calling
- 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
- After contract upgrades, re-verify compute_salt's signature matches the SDK's call
- Keep function_arguments construction next to the Move function's definition
- Log dev-inspect status/error when returnValues is empty to get the real abort code
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
- No return value from channel_balance
- Wallet does not support standard:connect
- No Sui account returned by wallet
- Invalid Sui signer: expected Ed25519Keypair
- Not a MoveObject
AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16).
Data as JSON: /api/errors/f9adbf8589ac25a5.
Report an issue: GitHub.