can1357/oh-my-pi · error · Error

seafile share response did not include a Location URL

Error message

seafile share response did not include a Location URL

What it means

The Seafile uploader expects the share-link creation response to yield a public URL, either from the Location header of a redirect (fetch is called with redirect: "manual") or from the JSON body's shareLink field. If neither is present, the response cannot be turned into a share URL and the upload fails fast with this error. It guards against silent misconfiguration of the Seafile server or an unexpected API response shape.

Source

Thrown at packages/coding-agent/src/blob-broker/uploaders-self-hosted.ts:433

			const shareForm = new URLSearchParams({
				p: `${directory === "/" ? "" : directory}/${filename}`,
				share_type: "download",
			});
			if (sharePassword) shareForm.set("password", sharePassword);
			if (expiryDays !== undefined && expiryDays > 0) shareForm.set("expire", String(expiryDays));
			const shareResponse = await expectOk(
				await requestFetch(`${endpoint(apiUrl, "repos", repositoryId, "file", "shared-link")}/`, {
					method: "PUT",
					headers: { ...headers, "Content-Type": "application/x-www-form-urlencoded" },
					body: shareForm,
					redirect: "manual",
				}),
				"seafile",
			);
			let location = shareResponse.headers.get("Location") ?? undefined;
			if (!location) location = shareLink(parseJsonText(await shareResponse.text()));
			if (!location) throw new Error("seafile share response did not include a Location URL");
			const resultUrl = new URL(location, apiUrl);
			if (raw) resultUrl.searchParams.set("raw", "1");
			return publication("seafile", request, resultUrl.toString(), {
				...(expiryInfo.expiresAt === undefined ? {} : { expiresAt: expiryInfo.expiresAt }),
			});
		},
	};
}

function plikFile(value: unknown): PlikFile | undefined {
	let candidate: unknown = value;
	if (Array.isArray(candidate)) candidate = candidate[0];
	if (typeof candidate === "object" && candidate !== null && "file" in candidate) candidate = candidate.file;
	if (typeof candidate !== "object" || candidate === null || !("id" in candidate)) return undefined;
	const id = identifier(candidate.id);
	if (!id) return undefined;
	const name =
		"fileName" in candidate

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the Seafile API base URL and token: curl the share-link endpoint manually and inspect the response body/headers
  2. Check the Seafile server version and confirm it returns shareLink (or sets Location) on POST /api/v2.1/share-links/
  3. Check for a reverse proxy rewriting/stripping the Location header
  4. Inspect the raw response body in logs to see the server's error message (e.g. permission denied on the library)

Example fix

// before: server returns error JSON with no shareLink
if (!location) throw new Error("seafile share response did not include a Location URL");
// after: log the body to diagnose
if (!location) throw new Error(`seafile share response did not include a Location URL: ${await shareResponse.text()}`);
Defensive patterns

Strategy: try-catch

Validate before calling

const res = await fetch(shareUrl, { method: "POST", headers, redirect: "manual" });
const loc = res.headers.get("Location") ?? (await res.json())?.shareLink;
if (!loc) throw new Error(`Seafile returned no share link: HTTP ${res.status}`);

Type guard

function hasShareLink(v: unknown): v is { shareLink: string } {
	return typeof v === "object" && v !== null && typeof (v as { shareLink?: unknown }).shareLink === "string";
}

Try / catch

try {
	await uploader.upload(req);
} catch (err) {
	if (err instanceof Error && err.message.includes("seafile share response")) {
		// log Seafile base URL/token, inspect server response, surface actionable message
	}
	throw err;
}

Prevention

When it happens

Trigger: The POST to the Seafile share-link endpoint (api/v2.1/share-links/) returns 2xx but includes no Location header and its JSON body lacks a usable shareLink value — e.g. the server responds with an empty body, an error object with no link field, or a non-redirect response because the endpoint path or auth token is wrong.

Common situations: Misconfigured SEAFILE server URL or API token causing the server to answer with a JSON error instead of a share link; a Seafile version whose share-link response format differs (older API versions return different field names); a reverse proxy stripping Location headers on manual-redirect responses.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/8dd88b691fed1a2a. Report an issue: GitHub.