Skip to content

Conversation

Copy link

Copilot AI commented Oct 12, 2025

Problem

When using the ListItemAttachments control to add or remove attachments on a list item being edited with DynamicForm, saving the form resulted in a 412 ETag conflict error:

Error making HttpClient request in queryable [412] ::> {"odata.error":{"code":"-1, Microsoft.SharePoint.Client.ClientServiceException","message":{"lang":"en-US","value":"The request ETag value '\"4\"' does not match the object's ETag value '\"66b3501f-75a0-4716-8884-b2d93681eded,5\"'."}}}

Root Cause

  1. DynamicForm loads a list item and stores its ETag for optimistic concurrency control
  2. User adds/removes attachments via ListItemAttachments, which modifies the item and changes its ETag on the server
  3. DynamicForm remains unaware of the ETag change
  4. When saving, DynamicForm sends the outdated ETag, causing SharePoint to reject the request with a 412 error

Solution

This PR implements a comprehensive solution with two key components:

1. Enhanced SPService Methods

Modified addAttachment() and deleteAttachment() in SPService.ts to return the updated item data (including the new ETag) after performing attachment operations. Both methods now:

  • Execute the attachment operation as before
  • Fetch the updated list item to retrieve the new ETag
  • Return the complete item data with odata.etag

2. Component Integration Pattern

Added callback mechanism to ListItemAttachments:

  • New optional onAttachmentChange callback prop that receives updated item data
  • Invoked automatically when attachments are added or removed
  • Allows parent components to react to ETag changes

Added public method to DynamicForm:

  • New updateETag(itemData) method to update the internal ETag state
  • Prevents 412 errors on subsequent save operations
  • Can be called by parent components when external modifications occur

Usage

import { DynamicForm } from '@pnp/spfx-controls-react/lib/DynamicForm';
import { ListItemAttachments } from '@pnp/spfx-controls-react/lib/ListItemAttachments';

export class MyFormComponent extends React.Component {
  private dynamicFormRef = React.createRef<DynamicForm>();

  private onAttachmentChange = (itemData: any): void => {
    // Update DynamicForm's ETag when attachments are modified
    if (this.dynamicFormRef.current) {
      this.dynamicFormRef.current.updateETag(itemData);
    }
  }

  public render() {
    return (
      <div>
        <ListItemAttachments
          listId={listId}
          itemId={itemId}
          context={context}
          onAttachmentChange={this.onAttachmentChange}
        />
        <DynamicForm
          ref={this.dynamicFormRef}
          context={context}
          listId={listId}
          listItemId={itemId}
          respectETag={true}
        />
      </div>
    );
  }
}

Changes

  • SPService.ts: Updated addAttachment() and deleteAttachment() to return item data
  • ListItemAttachments components: Added onAttachmentChange callback prop and implementation
  • DynamicForm: Added public updateETag(itemData) method
  • Documentation: Updated with new properties, methods, and integration examples

Backward Compatibility

All changes are fully backward compatible:

  • The onAttachmentChange callback is optional
  • Existing code using ListItemAttachments continues to work without modifications
  • The updateETag method is a new public method that doesn't affect existing functionality

Testing

Tested scenarios:

  • Adding attachments while editing a form
  • Removing attachments while editing a form
  • Saving the form after attachment modifications
  • Backward compatibility with existing implementations

Fixes #4696

Original prompt

This section details on the original issue you should resolve

<issue_title>Using ListItemAttachments to add/remove attachments causes ETag errors</issue_title>
<issue_description>#### Category
[ ] Enhancement

[X] Bug

[X] Question

Version

Please specify what version of the library you are using: 3.22.0

Expected / Desired Behavior / Question

When using ListItemAttachment to add or remove an attachment to the list item that the updated etag would be returned so that the dynamic edit form will be able save.

Observed Behavior

When using the ListItemAttachments control in edit view for a DynamicForm to either attach or remove files, upon save the following error is received (with various different values for ETag in the message of course).

Error making HttpClient request in queryable [412] ::> {"odata.error":{"code":"-1, Microsoft.SharePoint.Client.ClientServiceException","message":{"lang":"en-US","value":"The request ETag value '"4"' does not match the object's ETag value '"66b3501f-75a0-4716-8884-b2d93681eded,5"'."}}}

Steps to Reproduce

Basic set up of with component. Open an existing item. If there is no file attached, select Add Attachment, if there is a file delete it. Edit the Title. Select Save.

I see in the network logs that the calls to the endpoints used by ListItemAttachment don't return the ETag for the associated list item.

_api/web/lists(@listId)/items(@itemid)/AttachmentFiles/add(FileName=@filename)
_api/web/lists(@listId)/items(@itemid)/AttachmentFiles
_api/web/lists(@listId)/items(@itemid)/AttachmentFiles/getByFileName(@filename)/RecycleObject

###Question or suggested workaround

It is probably Microsoft's issue that updating the attachments update the Etag for the item, but don't report it. So if there isn't a way to get that information directly from the Attachments control, is there a way for the ListItemAttachments to raise events such as onComplete or onChange or some such. I see there are several private events in the class.

As a workaround we are setting respectETag={false} on the DynamicForm, but that can cause other issues.
</issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #2051


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Thank you for the first contribution to this project.

Copilot AI and others added 2 commits October 12, 2025 21:26
Modified SPService methods (addAttachment and deleteAttachment) to return the updated item with new ETag.
Added onAttachmentChange callback prop to ListItemAttachments and UploadAttachment components.
Components now notify parent components when attachments are modified so ETag can be updated.

Co-authored-by: AJIXuMuK <17036219+AJIXuMuK@users.noreply.github.com>
Added public updateETag method to DynamicForm to allow external updates when list item is modified.
Updated documentation for both ListItemAttachments and DynamicForm with integration examples.
This completes the fix for ETag conflict errors when using attachments with DynamicForm.

Co-authored-by: AJIXuMuK <17036219+AJIXuMuK@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix ETag errors with ListItemAttachments on save Fix ETag conflict errors when using ListItemAttachments with DynamicForm Oct 12, 2025
Copilot AI requested a review from AJIXuMuK October 12, 2025 21:33
Copilot finished work on behalf of AJIXuMuK October 12, 2025 21:33
@AJIXuMuK AJIXuMuK marked this pull request as ready for review October 12, 2025 22:49
@AJIXuMuK AJIXuMuK merged commit f1e3367 into dev Oct 12, 2025
2 checks passed
@AJIXuMuK AJIXuMuK deleted the copilot/fix-etag-errors-attachments branch October 12, 2025 22:50
@AJIXuMuK AJIXuMuK added this to the 3.23.0 milestone Oct 12, 2025
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