langgenius/dify · error · FileUploadError
${context} requires FormData
Error message
${context} requires FormData What it means
Thrown by the private ensureFormData() helper in knowledge-base.ts:46 as a FileUploadError. Three knowledge-base methods use it — createDocumentByFile, updateDocumentByFile, and uploadPipelineFile — each passing a context string so the message identifies which call site rejected the non-FormData argument. Like error 120, it requires a genuine FormData instance because the underlying endpoints are multipart uploads.
Source
Thrown at sdks/nodejs-client/src/client/knowledge-base.ts:46
DatasourceNodeRunRequest,
PipelineRunRequest,
KnowledgeBaseResponse,
PipelineStreamEvent,
} from '../types/knowledge-base'
import { FileUploadError, ValidationError } from '../errors/dify-error'
import { isFormData } from '../http/form-data'
import { DifyClient } from './base'
import {
ensureNonEmptyString,
ensureOptionalBoolean,
ensureOptionalInt,
ensureOptionalString,
ensureStringArray,
} from './validation'
function ensureFormData(form: unknown, context: string): asserts form is SdkFormData {
if (!isFormData(form)) {
throw new FileUploadError(`${context} requires FormData`)
}
}
const ensureNonEmptyArray = (value: unknown, name: string): void => {
if (!Array.isArray(value) || value.length === 0) {
throw new ValidationError(`${name} must be a non-empty array`)
}
}
export class KnowledgeBaseClient extends DifyClient {
async listDatasets(options?: DatasetListOptions): Promise<DifyResponse<KnowledgeBaseResponse>> {
ensureOptionalInt(options?.page, 'page')
ensureOptionalInt(options?.limit, 'limit')
ensureOptionalString(options?.keyword, 'keyword')
ensureOptionalBoolean(options?.includeAll, 'includeAll')
const query: QueryParams = {
page: options?.page,View on GitHub (pinned to ef8544b173)
Solutions
- Build a FormData, append both 'file' and the 'data' JSON field the server expects, then pass it: const form = new FormData(); form.append('file', fileHandle); form.append('data', JSON.stringify({...})); await kb.createDocumentByFile(datasetId, form, user).
- On Node < 18 import a form-data polyfill so isFormData() returns true via getHeaders() or constructor.name.
- Use createDocumentByText(datasetId, { name, text, ... }, user) instead if you only have raw text and want to avoid multipart entirely.
- Verify the variable you pass is the FormData instance itself, not a wrapper object holding it.
Example fix
// before
await kb.createDocumentByFile(datasetId, { name: 'doc', file: '/p.pdf' }, user)
// after
import FormData from 'form-data'
const form = new FormData()
form.append('file', fs.createReadStream('/p.pdf'))
form.append('data', JSON.stringify({ name: 'doc', indexing_technique: 'high_quality' }))
await kb.createDocumentByFile(datasetId, form, user) Defensive patterns
Strategy: type-guard
Validate before calling
import { isFormData } from '@dify-platform/dify-client/src/http/form-data'
function assertDocForm(form: unknown, ctx: string) {
if (!isFormData(form)) throw new Error(`${ctx} requires FormData`)
} Type guard
import { isFormData } from '@dify-platform/dify-client/src/http/form-data'
function isDocumentForm(value: unknown): value is FormData {
return isFormData(value)
} Try / catch
try {
await kb.createDocumentByFile(ds, form, user)
} catch (err) {
if (err instanceof Error && err.name === 'FileUploadError' && /requires FormData/.test(err.message)) {
// rebuild form and retry once
} else throw err
} Prevention
- Centralize document-upload form construction in one helper so the same FormData shape is reused.
- Prefer createDocumentByText when you have only text content.
- Log form.constructor.name in dev to confirm isFormData recognition.
When it happens
Trigger: Calling knowledgeBase.createDocumentByFile(datasetId, payload, user) (or updateDocumentByFile / uploadPipelineFile) where payload is not a FormData: a plain object, a Buffer, a string path, or undefined. The assert at knowledge-base.ts:45 fails and the FileUploadError is thrown synchronously with the method name interpolated.
Common situations: Switching from the text-based createDocumentByText to the file variant and forgetting to wrap the file in FormData; passing { file, data } as a JSON object; using an outdated form library whose instances fail isFormData(); Node environments without a FormData global and no polyfill.
Related errors
- FormData is required for audio uploads
- ${name} must be a non-empty array
- metadata must be one of all, only, without
- no_file
- too_many_files
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/83c550a6550a6200.
Report an issue: GitHub.