Recently, I was working on an SPFx web part that would allow employees to upload their documents along with metadata to a SharePoint document library. The web part includes a form with input controls for the library columns.
To help with debugging, I also displayed logs in the web part, just below the form. When I clicked the Submit button after filling out all the fields, the following error appeared in the logs:
Error: Error making HttpClient request in queryable [400] ::> {"odata.error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"An unexpected 'StartArray' node was found when reading from the JSON reader. A 'PrimitiveValue' node was expected."}}}
This error indicates that SharePoint expected a primitive (single) value but received an array.
Let’s see how to resolve this SPFx error while saving data to a SharePoint library, and we’ll also discuss the scenarios in which it occurs.
Understanding the StartArray vs PrimitiveValue Issue
Below is the SharePoint document library that I used as a datasource to my SPFx web part. The library contains a Choice column named Disability, which allows multiple selections.
For my requirement, users can select more than one option. However, I mistakenly forgot to enable the “Allow multiple selections” setting for this column.

In the SPFx web part below, I used checkbox controls for the Disability field so users can select multiple options. When I clicked the submit button, the web part sent all the selected values of this choice field as an array.
But since the library column was configured to accept only a single value, SharePoint rejected the request and returned the StartArray/PrimitiveValue error.

An unexpected startarray node was found
After enabling the “Allow multiple selections” setting in the SharePoint document library choice field, this error disappeared.
If you are still facing this issue even after enabling that option, please check the following .tsx file code of the SPFx React web part. It will be helpful to you to send the multiple-choice values to the library.
import * as React from "react";
import { SPFI } from "@pnp/sp";
interface IProps {
sp: SPFI;
}
interface IState {
Disability: string[];
file: File | null;
statusMessage: string;
}
export default class DisabilityUpload extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
Disability: [],
file: null,
statusMessage: ""
};
}
// Multi-select checkbox handler
private handleMultiSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
const { value, checked } = e.target;
let selected = [...this.state.Disability];
if (checked) {
if (!selected.includes(value)) selected.push(value);
} else {
selected = selected.filter((v) => v !== value);
}
this.setState({ Disability: selected });
};
// File selection
private handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ file: e.target.files ? e.target.files[0] : null });
};
// Submit upload file + update metadata
private submitData = async () => {
const { Disability, file } = this.state;
if (!file) {
this.setState({ statusMessage: "Please select a file first." });
return;
}
try {
const libraryPath = "/sites/SPFXDevelopment/USACitizenship";
const folder = this.props.sp.web.getFolderByServerRelativePath(libraryPath);
// Upload file
await folder.files.addUsingPath(file.name, file, { Overwrite: true });
const fileUrl = `${libraryPath}/${file.name}`;
const spFile = this.props.sp.web.getFileByServerRelativePath(fileUrl);
const item = await spFile.getItem();
// Update metadata (Disability is now a multi-choice array)
await item.update({
Disability: Disability
});
this.setState({ statusMessage: "Submitted successfully!" });
} catch (error: any) {
this.setState({ statusMessage: "Error: " + error.message });
}
};
public render() {
return (
<div style={{ padding: "20px" }}>
<h3>Disability Selection + File Upload</h3>
{/* Checkboxes */}
<div>
<label>
<input
type="checkbox"
value="I am deaf or hearing impaired"
onChange={this.handleMultiSelect}
checked={this.state.Disability.includes("I am deaf or hearing impaired")}
/>
I am deaf or hearing impaired
</label>
<label>
<input
type="checkbox"
value="I use a wheelchair"
onChange={this.handleMultiSelect}
checked={this.state.Disability.includes("I use a wheelchair")}
/>
I use a wheelchair
</label>
<label>
<input
type="checkbox"
value="I am blind or sight impaired"
onChange={this.handleMultiSelect}
checked={this.state.Disability.includes("I am blind or sight impaired")}
/>
I am blind or sight impaired
</label>
<label>
<input
type="checkbox"
value="I need another type of accommodation"
onChange={this.handleMultiSelect}
checked={this.state.Disability.includes("I need another type of accommodation")}
/>
I need another type of accommodation
</label>
</div>
{/* File Input */}
<br />
<input type="file" onChange={this.handleFileSelect} />
{/* Submit Button */}
<br /><br />
<button onClick={this.submitData}>Submit</button>
{this.state.statusMessage && (
<p style={{ marginTop: "10px", color: "blue" }}>
{this.state.statusMessage}
</p>
)}
</div>
);
}
}
Here:
- At the start, I created an IState to keep the Disability choices, the file input, and the status messages.
- Then, in the constructor(), I initialized it with default values:
- Disability with an empty array.
- file with a null value.
- statusMessage with an empty string.
- In the render() method, I displayed the file input control, checkboxes, and a button control in a form.
- Every checkbox is connected to handleMultiSelect(). When a user clicks a checkbox:
- If checked, the value is added to the Disability[].
- If unchecked, the value is removed from Disability[] array.
- The state always stores the latest selected options.
- Every checkbox is connected to handleMultiSelect(). When a user clicks a checkbox:
- File input calls the handleFileSelect() method when the user uploads a file.
- When the submitData() method runs, it first checks if the file exists; if yes, it continues to upload the file and get that record to update metadata.
- To update metadata, we are using the await item.update({..}) PnPJS method, so here, for the Disability field, we assign the state Disability array directly.
- Since we enabled the allow multiple selection setting for the choice field, it will now accept an array of options.
You can compare your code with this one, mainly how you created the state and collected all the choice values, sending them to a list/library.
Conclusion
This is how to fix the error: an unexpected startarray node was found when reading from the json reader. This error will occur not only for the choice fields, but also for the person or group fields in the SharePoint list/library if it does not allow multiple selection, and you send multiple values to it.
Do let me know if this helps you.
Also, look at some other SPFx error-solving blog posts:
- [spfx-serve] The api entry could not be loaded: node_modules/@microsoft/sp-webpart-workbench/lib/api/ in SharePoint Framework
- No gulpfile found error in SharePoint Framework (SPFx)
- Fix SPFx Error: An unexpected ‘StartObject’ node was found when reading from the JSON reader. A ‘StartArray’ node was expected.
- SPFx Error: Couldn’t add this app. Check your network connection and try again

Hey! I’m Bijay Kumar, founder of SPGuides.com and a Microsoft Business Applications MVP (Power Automate, Power Apps). I launched this site in 2020 because I truly enjoy working with SharePoint, Power Platform, and SharePoint Framework (SPFx), and wanted to share that passion through step-by-step tutorials, guides, and training videos. My mission is to help you learn these technologies so you can utilize SharePoint, enhance productivity, and potentially build business solutions along the way.