gitbutlerapp/gitbutler · error · napi::Error
invalid ' ' at index
Error message
invalid '{}' at index {index}: {e} What it means
This error is generated by the but_api NAPI macro when converting a Vec<String> parameter back into Vec<gix::ObjectId> for a GitButler API call. One of the strings in the array is not a valid Git object ID (40-char SHA-1 or 64-char SHA-256 hex). The inner gix::hash::decode::Error is wrapped into a napi::Error with Status::InvalidArg, naming the parameter and the failing array index.
Solutions
- Print and inspect the array element at the reported index and fix it to a full valid hex object ID
- Verify the object actually exists (git rev-parse <value>) before calling the API
- Check that you are not passing branch/ref names where object IDs are required
- Ensure consistent hash length (40 vs 64 chars) matching the repository's object format
Example fix
// before api.commitFiles(['abc123', '9f8e7d...']); // truncated id // after api.commitFiles(['9f8e7d6c5b4a3210fedcba9876543210abcdef12']); // full 40-char hex
Defensive patterns
Strategy: validation
Validate before calling
function isValidObjectId(s) { return typeof s === 'string' && /^[0-9a-f]{40}$|^[0-9a-f]{64}$/.test(s); }
ids.forEach((id, i) => { if (!isValidObjectId(id)) throw new Error(`bad object id at index ${i}: ${id}`); }); Type guard
const isObjectId = (v: unknown): v is string => typeof v === 'string' && /^[0-9a-f]{40}([0-9a-f]{24})?$/.test(v); Try / catch
try { api.commitFiles(ids); } catch (e) { if (String(e.message).includes('invalid')) { const idx = /index (\d+)/.exec(e.message); console.error('bad id at', idx?.[1]); } throw e; } Prevention
- Always pass full-length hex hashes, never short prefixes
- Resolve ref names to object IDs before calling ID-typed APIs
- Validate array elements with a hex regex before batch calls
When it happens
Trigger: Calling any generated but_api NAPI function whose parameter maps to Vec<gix::ObjectId> (via maps_vec_object_id_to_vec_string_napi_param_and_parser) with an array containing a string that fails gix::hash::from_str decoding — e.g. wrong length, non-hex characters, or an empty string in the array.
Common situations: JS/TS callers pass truncated commit IDs from UI copy/paste, pass branch names instead of object IDs, pass IDs from a different hash algorithm, or include null/undefined coerced to 'null'/'undefined' strings inside the array.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- argument ' ' must be a non-negative integer that fits in…
- argument ' ' must be an integer that fits in isize
- InvalidArg
- Cannot cherry-pick above a reference
- Cannot derive a worktree directory from
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/de58154473ce0253.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-api-macros/src/lib.rs:1577
napi::Status::InvalidArg,
format!("invalid '{}': {e}", stringify!(#param_name)),
)
})
})
.transpose()?;
});
call_arg_idents.push(quote! { #ident });
} else if *last_ident == "Vec" && is_hex_hash_container_path(&mapping.json_ty, "Vec") {
// Vec<ObjectId> via Vec<HexHash> → Vec<String>, then parse each entry
params.push(quote! { #param_name: Vec<String> });
names.push(param_name.to_string());
conversions.push(quote! {
let #ident: Vec<gix::ObjectId> = #param_name
.into_iter()
.enumerate()
.map(|(index, value)| {
::std::str::FromStr::from_str(&value).map_err(|e: gix::hash::decode::Error| {
napi::Error::new(
napi::Status::InvalidArg,
format!("invalid '{}' at index {index}: {e}", stringify!(#param_name)),
)
})
})
.collect::<std::result::Result<Vec<_>, napi::Error>>()?;
});
let call_ident = match &*pat_ty.ty {
syn::Type::Reference(r) => {
let mutability = &r.mutability;
quote! { &#mutability #ident }
}
_ => quote! { #ident },
};
call_arg_idents.push(call_ident);
} else {
// Fallback: use serde_json::Value with ts_arg_type for proper TS typing
let ts_type_str = type_to_ts_name(&pat_ty.ty);View on GitHub (pinned to 58e5313667)