can1357/oh-my-pi · error · LegacyDestinationError
the upload response omitted URL components
Error message
the upload response omitted URL components
What it means
Thrown when the s-ul.eu upload endpoint returns 200 with no 'error' field, but the JSON is missing one or more of the required URL components: protocol, domain, or filename. The uploader builds the final public URL from these fields, so an incomplete response cannot be published. It indicates an unexpected or partially-failed upstream response.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders-legacy.ts:212
} catch (error) {
throw failure(destination, error);
}
return {
destination,
async upload(request) {
try {
const body = multipartFile(request, "file", { wizard: "true", key: apiKey, client: "sharex-native" });
const response = await fetchFor(config)(SUL_UPLOAD_URL, { method: "POST", body });
await expectOk(response, destination);
const data = await jsonObject(destination, response);
const upstreamError = firstString(data, ["error"]);
if (upstreamError) throw new LegacyDestinationError(destination, `upload rejected: ${upstreamError}`);
const protocol = firstString(data, ["protocol"]);
const domain = firstString(data, ["domain"]);
const filename = firstString(data, ["filename"]);
const extension = firstString(data, ["extension"]) ?? "";
if (!protocol || !domain || !filename) {
throw new LegacyDestinationError(destination, "the upload response omitted URL components");
}
const url = httpUrl(destination, `${protocol}${domain}/${filename}${extension}`);
const deleteUrl = new URL(SUL_DELETE_URL);
deleteUrl.searchParams.set("key", apiKey);
deleteUrl.searchParams.set("file", filename);
return publication(destination, request, url, {
delete: { method: "GET", url: deleteUrl.href },
remoteId: filename,
});
} catch (error) {
throw failure(destination, error);
}
},
};
}
function createPuushUploader(config: DestinationRuntimeConfig, endpoint: URL): BlobUploader {
const destination = "puush" as const;View on GitHub (pinned to 9690622007)
Solutions
- Log the raw response body to see what the server actually returned
- Retry the upload — transient upstream degradation often produces incomplete payloads
- Check s-ul.eu API status/docs for schema changes and update the integration
- If persistent, switch the destination to a replacement endpoint configuration
Example fix
// before: assume every response has URL components
const data = await jsonObject(destination, response);
// after: log-and-retry on incomplete payloads
const data = await jsonObject(destination, response);
if (!firstString(data, ["protocol"]) || !firstString(data, ["domain"]) || !firstString(data, ["filename"])) {
throw new RetryableUploadError(`incomplete response: ${JSON.stringify(data)}`);
} Defensive patterns
Strategy: validation
Validate before calling
function looksLikeSulUploadResponse(data: unknown): boolean {
if (typeof data !== "object" || data === null) return false;
const r = data as Record<string, unknown>;
return typeof r.protocol === "string" && typeof r.domain === "string" && typeof r.filename === "string";
}
// call after parsing, before relying on the URL Type guard
function isCompleteSulResponse(d: unknown): d is { protocol: string; domain: string; filename: string; extension?: string } {
const r = d as Record<string, unknown>;
return typeof r?.protocol === "string" && r.protocol.length > 0 && typeof r?.domain === "string" && r.domain.length > 0 && typeof r?.filename === "string" && r.filename.length > 0;
} Try / catch
try {
return await uploader.upload(request);
} catch (err) {
if (err instanceof Error && /omitted URL components/.test(err.message)) {
// retry once or fall back to another destination
return fallbackUploader.upload(request);
}
throw err;
} Prevention
- Log raw response bodies on upload failure to detect schema drift early
- Pin a known-good replacement endpoint rather than relying on a public service's undocumented schema
- Monitor the upstream service for API changes
- Implement a fallback destination for critical publications
When it happens
Trigger: POST to SUL_UPLOAD_URL returns valid JSON lacking protocol/domain/filename keys — e.g. a success acknowledgement without URL data, an HTML error page parsed as JSON-ish, or a schema change on the s-ul side.
Common situations: s-ul.eu API schema drift; proxy/interception middleware stripping or rewriting response bodies; the service degrading and returning truncated success payloads.
Related errors
- upload rejected: ${upstreamError}
- the replacement endpoint rejected the upload
- the replacement endpoint did not return a direct image URL
- the replacement endpoint omitted the uploaded URL
- OpenAI stream response has no body (status ${response.status
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/c356388aed9e519c.
Report an issue: GitHub.