FlowiseAI/Flowise · error · Error
Document object must contain pageContent and metadata
Error message
Document object must contain pageContent and metadata
What it means
CustomDocumentLoader ran the user's javascriptFunction in a sandbox and the output was an array (output='document'), but the first element does not satisfy the document shape: pageContent must be a string AND metadata must be an object. This is a contract check on sandbox output, not a network or parse error.
Source
Thrown at packages/components/nodes/documentloaders/CustomDocumentLoader/CustomDocumentLoader.ts:134
}
const sandbox = createCodeExecutionSandbox(input, variables, flow, additionalSandbox)
try {
const response = await executeJavaScriptCode(javascriptFunction, sandbox, {
libraries: ['axios']
})
if (output === 'document' && Array.isArray(response)) {
if (response.length === 0) return response
if (
response[0].pageContent &&
typeof response[0].pageContent === 'string' &&
response[0].metadata &&
typeof response[0].metadata === 'object'
)
return response
throw new Error('Document object must contain pageContent and metadata')
}
if (output === 'text' && typeof response === 'string') {
return handleEscapeCharacters(response, false)
}
return response
} catch (e) {
throw new Error(e)
}
}
}
module.exports = { nodeClass: CustomDocumentLoader_DocumentLoaders }
View on GitHub (pinned to abe4a8601a)
Solutions
- Map every element explicitly: return response.data.map(item => ({ pageContent: String(item.text), metadata: { id: item.id } })).
- Ensure pageContent is coerced to a string and metadata is always an object (use {} as fallback if you want it to pass).
- Test the sandbox function standalone with a sample input before wiring it into the node.
Example fix
// before
// user function returned: [{ text: 'hi' }]
// after - shape each row to the contract
const docs = response.data.map((item) => ({
pageContent: String(item.text ?? ''),
metadata: { id: item.id, source: item.url }
}))
return docs Defensive patterns
Strategy: type-guard
Type guard
import type { IDocument } from './types'
function isDocumentArray(value: unknown): value is IDocument[] {
if (!Array.isArray(value) || value.length === 0) return false
return value.every((item) =>
item !== null && typeof item === 'object'
&& typeof (item as any).pageContent === 'string'
&& (item as any).metadata !== null && typeof (item as any).metadata === 'object'
)
}
// if (output === 'document' && isDocumentArray(response)) return response
// else throw with available-fields diagnostics Prevention
- In your sandbox function, always map rows to { pageContent: String(...), metadata: {...} }.
- Coerce pageContent with String() so numbers/undefined become strings.
- Return [] rather than a malformed array when there are no results.
When it happens
Trigger: The function returned [{text: ...}] instead of [{pageContent, metadata}]; pageContent is a number or undefined; metadata is missing or is a string; the function returned the raw axios response object instead of mapped documents.
Common situations: User wrote the sandbox function against a different schema; the API they fetched from returned objects that were not mapped; only checked length>0 but element shape is wrong.
Related errors
- ${e}
- Invalid JSON in the Custom Document Loader Input Variables:
- Returned message history must be an array
- Security validation failed: ${error.message}
- ${e}
AI-assisted analysis of FlowiseAI/Flowise@abe4a8601a (2026-08-12).
Data as JSON: /api/errors/811f71f42036567d.
Report an issue: GitHub.