Pnpjs: Error 0x80131904 when adding items to a Sharepoint Online list

Created on 26 May 2020  Â·  11Comments  Â·  Source: pnp/pnpjs

I created two custom webparts using react and the pnpjs library:

  • A Forms Webpart that allows me to consult, add or edit items in lists of my sharepoint site.
  • A Migration Webpart that allows to migrate list items from my previous sharepoint site to my new one. It takes all the list items in a previous site of mine and adds them in a new site, with a slightly different structure.

Migration goes without any issue, all my previous site items are pasted to my new one. Once migration done, my other webpart allows me to consult and edit my items, as planned. However, impossible to add new items in certain lists ! I get this error :

Error making HttpClient request in queryable [500] Internal Server Error ::> {"odata.error":{"code":"-2146232060, Microsoft.SharePoint.SPException","message":{"lang":"fr-FR","value":"Exception from HRESULT: 0x80131904"}}}

However, the method I use to add items to these lists is stricly identical to the one I used during migration (using pnpjs). I then tried to add items in these lists directly via sharepoint online forms, and get a similar error :

Erreur : Exception from HRESULT: 0x80131904

After reading some forums, I could see that it could be due to a lack of space in the site, however my storage metrics shows that I use less than 0.1%. I also read some possible issues with a temp DB, but sharepoint online has none.

Notes :

  • It sometimes happens that I can add items to these lists. It happens randomly and rarely more than once in a row. I could not find any correlation of this with anything, it seems completely random to me.
  • I noticed that this problem occured with the lists that were the more populated (more than 100 items). However, all of my lists contain less than 4000 items, which should not be a problem.
  • In lists that contain few items, I can add some with my webpart or sharepoint online forms with no issue.
  • I also noticed that when I delete items from these lists, I could then add a few. But this is not a solution since the problem eventualy comes back, and I don't want to delete any items from these lists anyway.
  • when I just create the new lists without populating them, my forms webpart works fine as well.
  • The problem occurs when I create the lists and then populate them with the migration webpart.
  • I read about some throttling issue that could be happening. If I understand it correctly, an account could be blocked from adding items after too many requests in a period of time. However in my case this problem persists after days, and with different accounts as well.
  • I also read that it could be a permission issue, but even trying to add with the account that created the lists and did the migration, the error persists.

_What I really don't get is how adding a large amount of items (using pnpjs) works just fine and then fails when using another webpart or sp online forms._

I sincerly hope that I will be able to solve this issue, thanks a lot to everyone !

Category

  • [ ] Enhancement
  • [x] Bug
  • [ ] Question
  • [ ] Documentation gap/issue

Version

Please specify what version of the library you are using: [ 2.0.2 ]

Please specify what version(s) of SharePoint you are targeting: [ Sharepoint Online ]

Expected / Desired Behavior / Question

I should be able to add items to any list, using pnpjs or sharepoint online forms, after a migration.

Observed Behavior

I'm not able to add items to certain lists after a migration.

Steps to Reproduce

Try adding items to lists after a heavy migration.

non-library investigate question

All 11 comments

I don't think this is a bug in the library, but something else. Appreciate all your notes we'll see if we can come up with any ideas but probably hard for us to reproduce.

It definitely doesn’t sound as a bug in the library, but “Something wrong with the tenant, site, or list, or even fields”. When API errors come they are mostly verbose. Also, as the same appears in OOTB form, it’s a sing to rise a support ticket after certain level of internal investigations to know how to reproduce exactly when support would ask for request ID. Throttling errors should return HTTP 429 error and different message, and time to wait until unblocked is usually minutes not days. I’d suggest partial migration to another site and tests if it behaves the same. And, TBH, it’s really nothing we can repro on our end.

Thank you very much for your quick answers. To be fair, I don't think it's a library related bug either, but I had to try ! I guess my last chance is to try and contact the support. I will keep you guys updated if you want. Thanks again

Yes, please keep us updated. If the case is resolved with description and something similar happening to others it’s more likely to find a solution or a clue what to do.

Sure, I will!

So my colleague (and friend) found an easy and miraculous solution to our problem. We just need to export the list component as a model (in the list parameters) and include the content. Then reimport the list using the created app (New App -> Name chosen for the app). And voilĂ , we can add any items to the list, using the OOTB forms or our custom webparts forms, no more errors !
We still don't know what caused this error, nor why this solution works, but it works.

In the meantime, MS support contacted me and I could share our problem and solution with them. Apparently they will be looking into it and should reach me when they find the reason of this issue.

So something was wrong in a list/content types/fields schemas on a new site. How did you migrate artifacts initially? Not sure it was mentioned here.

It's better to avoid save lists as a template where ever possible. It's considered as really really bad practice for years. It only works in tiny scopes but a huge trap in the long run.

I'd suggest provisioning using PnP Provisioning Engine, using provisioning templates, and Apply-PnPProvisioningTemplate in particular.

I did everything in my webpart, in js, using pnpjs.
My function to create lists looks like this:

  const create_Tmp_lists = async () => {
    setCreate_Tmp_step("loading")
    setLoading(true)
    setEnsured(false)

    for (let index = 0; index < array.length; index++) {
      const {
        list,
        fields = [],
        items = []
      } = array[index]
      list = "Tmp" + list
      pushAndLog(`Ensuring list ${list}...`)
      const listEnsureResult = await sp.web.lists.ensure(list);
      const mylist = sp.web.lists.getByTitle(list)

      // check if the list was created, or if it already existed:
      if (listEnsureResult.created) {
        pushAndLog(`List ${list} was created!`);
        pushAndLog(`Adding fields to list ${list}...`);
        for (let i = 0; i < fields.length; i++) {
          let field = fields[i];
          const {
            title,
            type = 'Text'
          } = field
          pushAndLog(`Adding field ${title} to list ${list}...`)
          switch (type) {
            case 'DateTime':
              const {
                displayFormat = DateTimeFieldFormatType.DateOnly,
                calendarType = CalendarType.Gregorian,
                friendlyDisplayFormat = DateTimeFieldFriendlyFormatType.Disabled
              } = field;
              await mylist.fields.addDateTime(title, displayFormat, calendarType, friendlyDisplayFormat);
              break;
            case 'Calculated':
              const {
                formula,
                dateFormat = DateTimeFieldFormatType.DateOnly,
                outputType = FieldTypes.Number
              } = field;
              await mylist.fields.addCalculated(title, formula, dateFormat, outputType);
              break;
            case 'Number':
              await mylist.fields.addNumber(title);
              break;
            case 'MultilineText':
              const {
                numberOfLines = 6,
                richText = true,
                restrictedMode = false,
                appendOnly = false,
                allowHyperlink = true
              } = field
              await mylist.fields.addMultilineText(
                title,
                numberOfLines,
                richText,
                restrictedMode,
                appendOnly,
                allowHyperlink);
              break;
            default: // Text
              await mylist.fields.addText(title);
          }
        }
        pushAndLog(`All fields have been added to list ${list}!`);

        if (items.length) {
          pushAndLog(`Adding items to ${list}...`)
          let chunkedItems = chunk(items)
          for (let chunkIndex = 0; chunkIndex < chunkedItems.length; chunkIndex++) {
            let chunkedItem = chunkedItems[chunkIndex]
            let batch = sp.web.createBatch()
            pushAndLog(`Adding ${chunkedItem.length} items to ${list} in Batch ${chunkIndex + 1} out of ${chunkedItems.length}`)
            for (let i = 0; i < chunkedItem.length; i++) {
              let item = chunkedItem[i]
              mylist.items.inBatch(batch).add(item).then(() => console.log(item));
            }
            await batch.execute()
          }
          pushAndLog(`All items have been added to list ${list}!`);
        } else {
          pushAndLog(`No items to add to list ${list}!`);
        }

        const view = mylist.defaultView;

        pushAndLog(`Adding fields to view ${list}...`)
        for (let i = 0; i < fields.length; i++) {
          let field = fields[i]
          let { title } = field
          pushAndLog(`Adding field ${title} to view ${list}...`)
          await view.fields.add(title);
        }
        pushAndLog(`All fields have been added to view ${list}!`)

      } else {
        pushAndLog(`List ${list} already existed!`);
      }
    }

    pushAndLog('All done!')

    setLoading(false)
    setEnsured(true)
    setCreate_Tmp_step("done")
  }

It uses an array of objects that look like this :

{
  list: 'CommentaireSuiviAction',
  fields: [
    {
      title: "Commentaire",
      type: "MultilineText"
    },
    {
      title: 'Date',
      type: 'DateTime'
    },
    {
      title: 'FicheSuiviId',
      type: 'Number'
    }
  ],
  items: [
    // {
    //   Title: "Test",
    //   Commentaire: "Un commentaire de test",
    //   FicheSuiviId: 1
    // }
  ]
}

I don't really know if this is a bad way to do it, however the creation (and population) works fine, and I have no errors adding items afterwards. Errors star appearing after my migration.
Migration is done using pnpjs aswell. I take all the items from a list in a previous site, then change some structure and add the items in one of the newly created list (using my provisioning code above).

Here is how the migration code could look like :

    // basic case to get paged items form a list
    const items = await oldWeb.lists.getByTitle('CommentaireSuiviAction').items.top(50).getPaged()
    console.log(items)
    const TmpCommentaireSuiviAction = sp.web.lists.getByTitle('TmpCommentaireSuiviAction')

    for (let batchIndex = 0; items.results.length > 0; batchIndex++) {
      const CommentaireSuiviAction = items.results
      console.log(CommentaireSuiviAction)
      let batch = sp.web.createBatch()
      pushAndLog(`Adding ${items.results.length} items to CommentaireSuiviAction in Batch ${batchIndex + 1}`)

      for (let i = 0; i < CommentaireSuiviAction.length; i++) {
        let item = CommentaireSuiviAction[i]
        let myItem = {
          ID: item.ID,
          Title: "" + item.Nom + ' ' + item.Prenom + ' - ' + item.Entreprise,
          Commentaire: item.CommentaireSuiviAction,
          Date: formatDate(item.DateCommentaireSuiviAction),
          FicheSuiviId: item.elementassocieId
        }
        TmpCommentaireSuiviAction.items.inBatch(batch).add(myItem).then(() => console.log(myItem))
      }
      await batch.execute()

      // the hasNext property is used with the getNext method to handle paging
      // hasNext will be true so long as there are additional results
      if (items.hasNext) {
        // this will carry over the type specified in the original query for the results array
        items = await items.getNext();
        // otherwise break the loop
      } else {
        items = {
          results: []
        }
      }
    }

Amongst mentioned, Calculated fields are peevish they could easily go nuts and also language-dependent formula-terms. Theoretically something wrong with the fields schemas. If not tired yet of this, can you compare fields schemas or in a broken list try removing fields one by one until the form works? My vote, if other field types are not omitted to shorten the sample, is for Calculated field issue.

Well I don't actually use calculated fields in every lists. The list I used for example "CommentaireSuiviAction" doesn't have any calculated fields.
I tried removing every fields except Title from this list, and the error persisted.

Going to close this as the discussion seems to be over. Glad you found a solution.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alirobe picture alirobe  Â·  3Comments

ITAndy23 picture ITAndy23  Â·  3Comments

KieranDaviesV picture KieranDaviesV  Â·  3Comments

AJIXuMuK picture AJIXuMuK  Â·  3Comments

drewcook picture drewcook  Â·  3Comments