Skip to content

Comments

Fix attachment streaming errors and add observability for failed attachments#136

Open
gasperzgonec wants to merge 16 commits intomainfrom
gasperz/ISS-247801
Open

Fix attachment streaming errors and add observability for failed attachments#136
gasperzgonec wants to merge 16 commits intomainfrom
gasperz/ISS-247801

Conversation

@gasperzgonec
Copy link
Contributor

@gasperzgonec gasperzgonec commented Jan 29, 2026

Description

This PR fixes the following issues:

  • Attachments of size 0 failing
  • Added more information for attachments that failed to upload

Connected Issues

Checklist

  • Tests added/updated and ran with npm run test OR no tests needed.
  • Ran backwards compatibility tests with npm run test:backwards-compatibility.
  • Code formatted and checked with npm run lint.
  • Tested airdrop-template linked to this PR.
  • Documentation updated and provided a link to PR / new docs OR no docs needed.

Before, some error messages contained [object Object], so I had to add
JSON.stringify(<error>) to fix that. I changed `. "+error` to `.",
error`, which automatically adds a space and stringifies the error.
@gasperzgonec gasperzgonec requested review from a team and radovanjorgic as code owners January 29, 2026 16:29
@gasperzgonec gasperzgonec changed the title Fix attachment streaming errors and add observability for failed attachments. Fix attachment streaming errors and add observability for failed attachments Jan 29, 2026
Comment on lines 804 to 811
return {
error: {
message:
`Error while streaming to artifact for attachment ID ${attachment.id}. Skipping attachment. ` +
JSON.stringify(serializeError(uploadedArtifactError)),
fileSize: fileSize,
},
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's think of solving this in serializeError or somewhere else (maybe even in emit - if string passed just forward, if not stringify and forward). Correct me if I am wrong but you stringified here (and on few other places) because ErrorRecord interface requires message to be a string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed how the serializeError works; it now returns strings no matter what. If it's JSON error, it stringifies it, so that we can remove the JSON.stringify calls everywhere.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check this? I remember we had issues in past when stringifying errors. Were getting empty objects as output sometimes and it was hard to debug.

);
if (fileError) {
return {
error: new Error(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check if we need to wrap this in Error?

Copy link
Contributor Author

@gasperzgonec gasperzgonec Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has to be an error, as we're returning Promise<UploadResponse>, which contains a field error, which is optional, but is of type ErrorRecord:

/**
 * UploadResponse is an interface that defines the structure of the response from upload through Uploader.
 */
export interface UploadResponse {
  artifact?: Artifact;
  error?: ErrorRecord;
}

/**
 * ErrorRecord is an interface that defines the structure of an error record.
 */
export interface ErrorRecord {
  message: string;
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but ErrorRecord is type defined by us, while Error is generic error constructor in JavaScript (which coincidentally has message field).

): Promise<UploaderResult<ArtifactToUpload>> {
const url = `${this.devrevApiEndpoint}/internal/airdrop.artifacts.upload-url`;

if (fileSize != null && fileSize! <= 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you actually made fileSize required parameter? I am not sure if we should do that because s3interact accepts size not to be specified in first this request if I remember correctly, but please check.

I would rather do sth like if(fileSize && fileSize >= 0) { return error }.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fileSize is not required. What this check is doing, is that if the fileSize is provided and it's either 0 or negative, we throw an error, as the fileSize cannot be negative and a size of 0 isn't allowed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay so we can check it with this only then: if(fileSize! <= 0) {return error}.

error: {
message: `Error while preparing artifact for attachment ID ${
attachment.id
}. Skipping attachment. ${JSON.stringify(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We stringify in serializeError already so we don't need to stringify here, right?

Comment on lines 804 to 811
return {
error: {
message:
`Error while streaming to artifact for attachment ID ${attachment.id}. Skipping attachment. ` +
JSON.stringify(serializeError(uploadedArtifactError)),
fileSize: fileSize,
},
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check this? I remember we had issues in past when stringifying errors. Were getting empty objects as output sometimes and it was hard to debug.


// If response is `undefined`, we have hit the timeout in the adapter.
if (!response) {
continue;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is response undefined if we hit adapter timeout? If there is soft timeout we can still finish this iteretion and next iteration will break from the while loop here.

);
if (fileError) {
return {
error: new Error(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but ErrorRecord is type defined by us, while Error is generic error constructor in JavaScript (which coincidentally has message field).

): Promise<UploaderResult<ArtifactToUpload>> {
const url = `${this.devrevApiEndpoint}/internal/airdrop.artifacts.upload-url`;

if (fileSize != null && fileSize! <= 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay so we can check it with this only then: if(fileSize! <= 0) {return error}.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants