paperclipai/paperclip · error · Error
Import transfer declaration returned no data.
Error message
Import transfer declaration returned no data.
What it means
Thrown by uploadCompanyImportTransfer when the POST to declare the transfer returns a falsy body. The server contract for /api/companies/.../imports/transfers requires a JSON object describing the transfer; an empty/204/null response means the API surface is broken or the client/server versions are out of sync.
Source
Thrown at cli/src/commands/client/company.ts:1158
}
/**
* Declare (or resume) the transfer for these zip bytes and upload every part
* the server reports missing, sequentially with per-part retries. Resolves
* with the transfer id once the server holds every part.
*/
export async function uploadCompanyImportTransfer(
api: Pick<PaperclipApiClient, "post" | "putRaw">,
zipBytes: Uint8Array,
opts: { onProgress?: (progress: ImportTransferUploadProgress) => void } = {},
): Promise<string> {
const manifest = buildImportTransferManifest(zipBytes);
const created = await api.post<CompanyImportTransferCreated>(
`/api/companies${COMPANY_IMPORT_TRANSFERS_ROUTE_PATH}`,
manifest,
);
if (!created) {
throw new Error("Import transfer declaration returned no data.");
}
if (created.alreadyCompleted) {
// The server keys transfers by content, and this exact zip already
// finished an apply — its spooled parts are gone, so it cannot re-run.
throw new Error(
"This exact package was already imported by a completed transfer. Re-export the package to import it again.",
);
}
const missing = new Set(created.missingParts);
let uploadedParts = manifest.parts.length - missing.size;
let uploadedBytes = manifest.parts.reduce(
(sum, part) => (missing.has(part.index) ? sum : sum + part.byteSize),
0,
);
for (const part of manifest.parts) {
if (!missing.has(part.index)) continue;
const offset = part.index * manifest.partSizeBytes;
const bytes = zipBytes.subarray(offset, offset + part.byteSize);View on GitHub (pinned to 67001ec6eb)
Solutions
- Verify the server is running a version that supports the imports/transfers route and returns the expected JSON.
- Check the API base URL and any proxy in front of it is not stripping response bodies.
- Update both server and CLI to compatible versions.
- Inspect the raw HTTP response with curl against /api/companies/.../imports/transfers to confirm the server emits a body.
- If this is a test double, ensure the mocked post returns a valid CompanyImportTransferCreated object.
Example fix
// before (mock returns nothing)
const api = { post: async () => undefined, putRaw: async () => {} };
await uploadCompanyImportTransfer(api, zipBytes);
// after
const created = { transferId: "tfr_1", missingParts: [0,1], alreadyCompleted: false };
const api = { post: async () => created, putRaw: async () => {} };
await uploadCompanyImportTransfer(api, zipBytes); Defensive patterns
Strategy: try-catch
Type guard
function isValidTransferCreated(v: unknown): v is { transferId: string; missingParts: number[]; alreadyCompleted: boolean } {
return (
typeof v === "object" && v !== null &&
typeof (v as any).transferId === "string" &&
Array.isArray((v as any).missingParts) &&
typeof (v as any).alreadyCompleted === "boolean"
);
} Try / catch
try {
const transferId = await uploadCompanyImportTransfer(api, zipBytes);
} catch (err) {
if (err instanceof Error && /returned no data/.test(err.message)) {
// server contract broken: surface to operator, check versions/proxy
throw new Error(`Import transfer endpoint returned empty body. Verify server version and proxy. Cause: ${err.message}`);
}
throw err;
} Prevention
- Keep CLI and server versions in lockstep.
- Smoke-test the transfers endpoint with curl after deploys.
- In test doubles, always return a valid CompanyImportTransferCreated object.
- Watch for proxies/gateways that strip response bodies.
When it happens
Trigger: The PaperclipApiClient.post call resolves to undefined (e.g. a 204 No Content, a proxy that strips the body, a server bug returning empty, or a version mismatch where the route exists but the response shape changed). Network middleware that replaces the body with null.
Common situations: Talking to an older server that does not implement the chunked transfer endpoint. A reverse proxy or gateway swallowing the response body. A mock client in tests that forgets to return the created object. Client/server version skew after an upgrade.
Related errors
- This exact package was already imported by a completed trans
- Existing-company imports require a companyId to resolve the
- Applying a company import with --json requires --yes. Use --
- Applying a company import from a non-interactive terminal re
- GitHub source must be a GitHub or GitHub Enterprise URL, or
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/7d9293dda3ae7a7c.
Report an issue: GitHub.