can1357/oh-my-pi · error
Pushbullet upload fields were missing from the destination r
Error message
Pushbullet upload fields were missing from the destination response
What it means
This error is thrown by the Pushbullet blob uploader after it calls POST /v2/upload-request. Pushbullet's upload-request response must contain `data` — an object of S3 presigned-POST fields (awsaccesskeyid, acl, key, signature, policy, content-type) needed to upload the file bytes. When the response body has no `data` object, the uploader cannot perform the S3 upload and throws instead of producing a partially-broken publication.
Source
Thrown at packages/coding-agent/src/blob-broker/uploaders-cloud-drives.ts:415
const authHeaders = { Authorization: `Basic ${btoa(`${apiKey}:`)}` };
return {
destination: "pushbullet",
async upload(request: BlobUploadRequest) {
const filename = fileNameFor(request);
const requestForm = new FormData();
requestForm.set("file_name", filename);
const uploadRequestResponse = await expectOk(
await fetchImpl(`${PUSHBULLET_API}/upload-request`, {
method: "POST",
headers: authHeaders,
body: requestForm,
}),
"pushbullet",
);
const uploadRequest = (await uploadRequestResponse.json()) as PushbulletUploadRequest;
const data = uploadRequest.data;
if (!data) throw new Error("Pushbullet upload fields were missing from the destination response");
const fileUrl = requiredText(uploadRequest.file_url, "Pushbullet file URL");
const fileType = requiredText(uploadRequest.file_type, "Pushbullet file type");
const uploadUrl = requiredText(uploadRequest.upload_url, "Pushbullet presigned upload URL");
const uploadFields = {
awsaccesskeyid: requiredText(data.awsaccesskeyid, "Pushbullet AWS access key id"),
acl: requiredText(data.acl, "Pushbullet upload ACL"),
key: requiredText(data.key, "Pushbullet upload key"),
signature: requiredText(data.signature, "Pushbullet upload signature"),
policy: requiredText(data.policy, "Pushbullet upload policy"),
"content-type": requiredText(data["content-type"], "Pushbullet upload content type"),
};
await expectOk(
await fetchImpl(uploadUrl, {
method: "POST",
body: multipartFile(request, "file", uploadFields),
}),
"pushbullet",
);View on GitHub (pinned to 9690622007)
Solutions
- Verify the API key is valid by calling GET /v2/user and confirm the account can create upload requests
- Log the raw upload-request response body to inspect what Pushbullet actually returned
- Check for a proxy, API gateway, or mock intercepting api.pushbullet.com and altering the body
- Pin/monitor the Pushbullet API for breaking changes and update the uploader's response parsing
- Retry the upload — transient gateway issues can produce empty bodies
Example fix
// before (stubbed/mock endpoint returns partial body)
const uploadRequest = await response.json();
// after (caller validates before treating it as valid)
const uploadRequest = await response.json();
if (!uploadRequest?.data?.policy || !uploadRequest?.upload_url) {
throw new Error(`Pushbullet upload-request response incomplete: ${JSON.stringify(uploadRequest).slice(0, 200)}`);
} Defensive patterns
Strategy: validation
Validate before calling
function isValidPushbulletUploadRequest(body) {
return !!body && typeof body === 'object' &&
typeof body.upload_url === 'string' &&
typeof body.file_url === 'string' &&
!!body.data && typeof body.data.policy === 'string' &&
typeof body.data.signature === 'string';
}
const uploadRequest = await res.json();
if (!isValidPushbulletUploadRequest(uploadRequest)) {
throw new Error('Pushbullet upload-request response incomplete');
} Type guard
function isPushbulletUploadRequest(v) {
return typeof v === 'object' && v !== null && 'data' in v &&
typeof v.upload_url === 'string';
} Try / catch
try {
const uploadRequest = await uploadRequestResponse.json();
if (!isPushbulletUploadRequest(uploadRequest)) {
throw new Error(`Pushbullet upload-request incomplete: ${JSON.stringify(uploadRequest).slice(0, 200)}`);
}
} catch (err) {
logger.error('Pushbullet upload-request failed', { cause: err });
throw err;
} Prevention
- Validate the upload-request response shape before using its fields
- Use a real, unproxied Pushbullet API key in production
- Log unexpected response bodies to detect API schema changes early
- Test against the live Pushbullet API, not partial mocks
When it happens
Trigger: POST to https://api.pushbullet.com/v2/upload-request returned 2xx but the parsed JSON body lacked a truthy `data` field — e.g. Pushbullet changed the response schema, a proxy/API gateway stripped or reshaped the body, or the endpoint returned a JSON body that is not the expected {file_url, upload_url, data:{...}} shape.
Common situations: Pushbullet API schema changes; corporate proxies or mock/stub servers returning a simplified 200 body; wrong or revoked API key that yields an unexpected 2xx body; tests hitting a mocked Pushbullet endpoint that only stubs part of the response.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- Gemini Files API ${context} response is not valid JSON
- Discord returned an invalid message response
- Backblaze B2 bucket listing omitted buckets
- seafile upload-link response did not include a URL
- Codex Security cloud returned an invalid object
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1ec4abec7e78a2f3.
Report an issue: GitHub.