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

  1. 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).
  2. On Node < 18 import a form-data polyfill so isFormData() returns true via getHeaders() or constructor.name.
  3. Use createDocumentByText(datasetId, { name, text, ... }, user) instead if you only have raw text and want to avoid multipart entirely.
  4. 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

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


AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12). Data as JSON: /api/errors/83c550a6550a6200. Report an issue: GitHub.