schollz/croc · error · Error
Invalid stored-transfer key
Error message
Invalid stored-transfer key
What it means
validateShare() requires the share key to be exactly 32 bytes (storedKeyBytes). The key comes from base64url-decoding the URL fragment (#v1....) or the token's last segment; a decode that yields any other length — from truncation, padding characters, or unicode mangling — is rejected before any decryption is attempted with it.
Source
Thrown at web/src/protocol/stored.ts:152
if (
(parsed.protocol !== "https:" && !(parsed.protocol === "http:" && loopback)) ||
parsed.username ||
parsed.password ||
(parsed.pathname !== "/" && parsed.pathname !== "") ||
parsed.search ||
parsed.hash
) {
throw new Error("Stored-transfer origin must contain only an HTTPS scheme and host");
}
return parsed.origin;
}
function validateShare(share: StoredShare) {
if (!/^[A-Za-z0-9_-]{22}$/.test(share.id)) {
throw new Error("Invalid stored-transfer id");
}
if (share.key.byteLength !== storedKeyBytes) {
throw new Error("Invalid stored-transfer key");
}
share.origin = normalizeOrigin(share.origin);
return share;
}
export function formatStoredBrowserURL(share: StoredShare) {
validateShare(share);
return `${share.origin}/s/${share.id}#v1.${base64URL(share.key)}`;
}
export function formatStoredCLIToken(share: StoredShare) {
validateShare(share);
return [
storedProtocol,
base64URL(textEncoder.encode(share.origin)),
share.id,
base64URL(share.key),
].join(".");View on GitHub (pinned to e25f1bdc04)
Solutions
- Copy the entire share URL including the #v1.<key> fragment; many chat clients require explicit 'copy link'
- If generating URLs yourself, base64URL-encode exactly the 32-byte key with no padding
- Pre-validate with a regex on the fragment length (43 unpadded base64url chars encode 32 bytes) before calling parseStoredShare
Example fix
// validation before parse
const keyPart = url.hash.slice(4);
if (!/^[A-Za-z0-9_-]{43}$/.test(keyPart)) throw new Error("Share link is missing its key fragment"); Defensive patterns
Strategy: validation
Validate before calling
const isValidShareKey = (key: Uint8Array): boolean => key.byteLength === 32;
// for the URL fragment: /^[A-Za-z0-9_-]{43}$/.test(hash.slice(4)) Prevention
- Check the #v1. fragment decodes to 43 unpadded base64url chars before parsing
- Copy share links whole; fragments are easy to lose in chat apps
When it happens
Trigger: parseStoredShare where fromBase64URL(parsed.hash.slice(4)) or parts[3] decodes to != 32 bytes; also createStoredUpload if wasm().storeGenerateKey() ever returned a different length (it does not in a consistent build).
Common situations: Share links mangled by messengers that strip or truncate the fragment; users copying only part of the URL and dropping the #v1. key fragment (usually caught as invalid URL first); mixing client versions where the key format changed.
Related errors
- Invalid stored-transfer id
- Invalid stored-transfer token
- Code must be at least 6 characters
- Custom codes must use printable ASCII characters
- Choose at least one file
AI-assisted analysis of schollz/croc@e25f1bdc04 (2026-08-15).
Data as JSON: /api/errors/2fe958a681782313.
Report an issue: GitHub.