I created two custom webparts using react and the pnpjs library:
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 :
_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 !
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 ]
I should be able to add items to any list, using pnpjs or sharepoint online forms, after a migration.
I'm not able to add items to certain lists after a migration.
Try adding items to lists after a heavy migration.
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.