'src.toArrayLike is not a function': Anchor u64 args need a BN in base units, not a JS number
Symptom: calling program.methods.list(0.005).accounts({...}) in a Next.js/TS client throws TypeError: src.toArrayLike is not a function, with no mention of the argument or the instruction.
Cause: Anchor serialises arguments with borsh layouts. For a 64-bit integer field the layout calls value.toArrayLike(Buffer, 'le', 8), a method that only exists on BN (bn.js). A JS number has no such method, so the failure surfaces deep in the encoder rather than as a type error. Numbers are accepted for u8/u16/u32, which is why some instructions work and others do not.
Fix:
import { BN } from '@coral-xyz/anchor';
await program.methods.list(new BN(5_000_000)).accounts({ ... }).transaction();The second trap: new BN(0.005) does not fix it. BN is an arbitrary-precision integer and either throws an assertion or silently truncates a fractional input. Convert to base units first — new BN(0.005 * LAMPORTS_PER_SOL) for SOL, or new BN(Math.round(amount * 10 ** mintDecimals)) for an SPL token, ideally building the integer with BigInt/string math to avoid float error on large values. For values above 2^53, pass a decimal string: new BN('18446744073709551615').
Related: new BN(x) for i64/u128 fields follows the same rule, and for Option<u64> pass null or a BN, never undefined.
Wrong guess to avoid: chasing the .accounts({...}) map or the IDL, because the error appears after the accounts are supplied. The offending value is always an argument, and grepping the IDL for u64/i64 fields on that instruction identifies it immediately.
Source: adapted from a Stack Exchange answer by Syed Aabis Akhtar (question by Berkay Çırak), https://solana.stackexchange.com/questions/15359/src-toarraylike-is-not-a-function — CC BY-SA 4.0
Confirmed with @coral-xyz/borsh + bn.js (Node 22): encoding a u64 field from a JS number throws 'TypeError: src.toArrayLike is not a function', and with new BN(5000000) it encodes 404b4c0000000000. On the second trap: new BN(0.005) doesn't assert, it silently returns 0. new BN(2**53+2) throws a bare 'Assertion failed'. Watch the post's own example, too: without rounding, 'new BN(x * LAMPORTS_PER_SOL)' truncates float error. 1.005 * 1e9 = 1004999999.9999999, and new BN() of that gives 1004999999, one lamport short with no error. Use Math.round as in your SPL example, or better, parse the decimal string into integer units (split on '.', pad the fraction to 9 digits, new BN(whole + frac)) so values beyond 2^53 base units work too.