jackwener/OpenCLI · error · CommandExecutionError
no signed url returned for attachment ${id}
Error message
no signed url returned for attachment ${id} What it means
A CommandExecutionError thrown after evaluating the in-page fetch snippet: the browser-context code ran but the returned data contained no url property, meaning no pre-signed download URL was obtained for the attachment. This indicates the signed-URL resolution step succeeded at the transport level but the server did not return a usable URL (auth/session issue, wrong attachment, or unexpected response shape).
Source
Thrown at clis/slock/attachment-download.js:57
columns: ['attachmentId', 'out', 'sizeBytes'],
func: async (page, kwargs) => {
const id = String(kwargs.attachmentId ?? '').trim();
if (!UUID_RE.test(id)) throw new ArgumentError(`attachmentId "${id}" is not a UUID`);
const out = path.resolve(String(kwargs.out ?? `./${id}.bin`));
// Step 1 — in-page, resolve the signed URL with the user's Slock session.
await page.goto(SLOCK_HOME_URL);
const snippet = buildFetchSnippet({
method: 'GET',
path: `/attachments/${encodeURIComponent(id)}/url`,
serverScoped: true,
serverIdOverride: kwargs.server,
});
const result = await page.evaluate(`(async () => { ${snippet} })()`);
const rows = dispatchEvaluateResult(result);
const data = Array.isArray(rows) ? rows[0] : rows;
const url = data?.url;
if (!url) throw new CommandExecutionError(`no signed url returned for attachment ${id}`);
// Step 2 — Node side, fetch the bytes from the signed CDN URL. No auth
// header (URL is pre-signed); no Origin (Node fetch has none) so CORS
// isn't in play.
let res;
try { res = await fetch(url); }
catch (e) { throw new CommandExecutionError(`network error fetching signed URL: ${e.message}`); }
if (!res.ok) {
throw new CommandExecutionError(`HTTP ${res.status} from signed CDN URL while downloading ${id}`);
}
const ab = await res.arrayBuffer();
fs.writeFileSync(out, Buffer.from(ab));
return [{ attachmentId: id, out, sizeBytes: ab.byteLength }];
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Re-authenticate / refresh the Slock browser session so the in-page fetch carries valid cookies
- Verify the attachmentId exists and is accessible for the active or overridden server (--server)
- Inspect the raw dispatchEvaluateResult payload (log `result`/`data`) to see the actual error the server returned
- Update buildFetchSnippet if the API response schema changed and the URL is under a new key
Example fix
// before
if (!url) throw new CommandExecutionError(`no signed url returned for attachment ${id}`);
// after
if (!url) throw new CommandExecutionError(
`no signed url returned for attachment ${id}; response=${JSON.stringify(data)}`
); Defensive patterns
Strategy: try-catch
Validate before calling
const data = Array.isArray(rows) ? rows[0] : rows;
if (!data || typeof data.url !== 'string' || !data.url.startsWith('http')) {
console.error('Signed-URL resolution failed:', JSON.stringify(data));
} Type guard
const hasSignedUrl = (d) => typeof d?.url === 'string' && d.url.length > 0;
Try / catch
try {
await attachmentDownload(page, { attachmentId: id });
} catch (e) {
if (/no signed url returned/.test(e.message)) {
console.error('Signed URL not issued — re-authenticate Slock session and verify the attachment exists');
} else throw e;
} Prevention
- Keep the Slock browser session fresh; re-login before batch downloads
- Confirm the attachment exists via a list/query command before downloading
- Log the evaluate result payload so auth/schema failures are visible, not just 'no url'
- Pin/verify the --server slug matches the environment holding the attachment
When it happens
Trigger: page.evaluate returned a result where data?.url is undefined — the in-page API call returned an error payload, an empty object, or a shape dispatchEvaluateResult maps to something without url, e.g. expired Slock session cookie, nonexistent attachmentId, or server-side denial.
Common situations: Slock session expired so the API returns an auth error object instead of a URL; the attachment was deleted or access-restricted; the server slug override (--server) points to an environment where the attachment doesn't exist; an API response schema change so the URL now lives under a different key.
Related errors
- Ctrip flight API returned HTTP ${status}; complete any verif
- TOS init multipart upload failed with status ${res.status}:
- Flomo memos requires an active signed-in Flomo browser sessi
- Unexpected Hupu probe: ${JSON.stringify(probe)}
- ${probe.detail}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/9b9358c96c12be86.
Report an issue: GitHub.