Skip to content

Troubleshooting

Something refused. This page is the index: every literal message a d2w fhir command or a build prints, what caused it, and what to do. Most of the causes turn out to be facts about your DHIS2 instance rather than faults in the tooling - a code with a < in it, an organisation unit a form is not assigned to, a program rule doing its job - so the fix is usually in DHIS2, and the message says which object.

Who this is for: the operator holding an error message. Find the literal text below, read the cause, apply the fix.

Before you start: nothing - this page is the index you grep when something refuses.

You will be able to: match the exact error text a d2w fhir command or a build printed to its cause and its fix.

Every refusal a d2w fhir command makes is an error: message on stderr with exit 1 - one per thing that is wrong, and no traceback. The exception is a fhir.toml value the settings document rejects outright, which comes out as the technical printout the settings file page reads for you. Publisher and SUSHI failures come out of the docker runs that drive them instead, in Java's voice; those are the second half of this page.

Project and configuration

Symptom (literal text) Cause Fix
error: no fhir.toml found in this directory or any parent. Run `d2w fhir init [DIRECTORY]` to scaffold a FHIR IG project first. A command that needs a project (generate, serve, forward) ran outside one. cd into the project, or scaffold one. validate is the exception - it runs anywhere.
no fhir.toml in <dir> - there is no project to refresh. Run `d2w fhir init <dir>` to scaffold one. init --refresh pointed at a directory that is not a project. Point it at the project root - the directory holding fhir.toml.
error: fhir.toml: unknown key '<key>' in [<section>], sometimes followed by did you mean '<name>'? fhir.toml names an option the settings document does not declare - usually a typo (max_lvl for max_level). One line per unknown key. Use the suggested spelling, or copy the option line out of fhir.example.toml. The settings file lists every option.
error: no profile named '<name>' (available: ...). Run `d2w profile list` to see all profiles. followed by a hint: block naming the same two commands The resolved profile does not exist in any profiles.toml. d2w profile list, then fix the -p flag, DHIS2_PROFILE, or the profile key in fhir.toml; d2w profile add <name> ... creates one.
warning: a profile named '<name>' also exists in the global scope; the project-scoped one will override it when you're in this directory. Not an error. d2w profile add --local wrote a project-scoped profile whose name is also in your global store. Nothing, if the override is what you wanted. Rename one of the two if it is not.
Font MPDFAA+NotoSans is missing the following glyphs: ... during d2w fhir validate Not a finding about your instance. The PDF writer met a character the bundled font has no drawing for, in a DHIS2 name or code it was rendering. Nothing - the .md and .csv reports carry the character regardless.
--refresh and --force are mutually exclusive: --force rewrites every scaffold file including the ones you edited, --refresh rewrites only what it can rewrite without losing your edits Both flags on one init run. Pick one: --refresh preserves edits, --force overwrites everything.
--refresh takes the project's identity and generation tables from its own fhir.toml, so <flags> would be ignored: drop the flag, or edit fhir.toml and refresh Identity flags (--id, --canonical, ...) passed together with --refresh. Edit fhir.toml, then refresh without the flags.
check-artifacts reports build-aborting references to .../registry/Location/<uid> or .../registry/Organization/<uid>, with the guide references an organisation unit the registry package it depends on does not publish The guide's [generate.organisation_units] selection is wider than the registry package's - most often an empty table in the guide, which reads the whole instance, while the package sets a root and a max_level. A form assigned to an organisation unit outside the package keeps that assignment. Give the guide the same root and max_level as the package, then d2w fhir generate in the guide. See the registry package.
--org-unit-max-level must be 1 or greater d2w fhir init --org-unit-max-level 0 (or negative) - it would silently produce an empty registry. Pass a level of 1 or more, or drop the flag.
Invalid value: --title carries '<'. The IG publisher writes this value into pages it strict-parses after writing, ... A --title or --name holding < or >. The publisher aborts its last pass on it, hours into a build, once every resource has already been rendered. Name the guide without the brackets.
Invalid value: --name yields the SUSHI name `<name>` , which FHIR does not accept: a name is an upper-case letter followed by up to 254 letters, digits or underscores. A --name outside the FHIR computer-friendly shape. SUSHI rewrites such a name into that shape without saying so, and the guide publishes a name nobody chose. Pass a name in the shape - SierraLeoneHmis - or drop --name and let it derive from --id.
Invalid value: --data-set carries '<value>', which is not a DHIS2 UID: eleven characters, an ASCII letter followed by ten letters or digits. A selection flag given something that is not a UID. Written through, it would select nothing and the guide would publish no form of that kind. Pass the UID; d2w metadata list dataSets names them.
Invalid value: --registry-path <path> names no directory: the project reads it from its own root, which puts it at <resolved>. --registry-path pointed at a directory that does not exist. The path is relative to the new project's own root, not to the shell's working directory. Scaffold the registry project at that path first, or drop the flag and let make build install the package from its id and version.
error: `<name>` is an example, not a template. followed by what it demonstrates --template named a guide of examples/igs/ whose template.toml says scaffolds = false - an exhibit rather than a template. Read the example where it lives; --list-templates names every guide you can scaffold from.
Invalid value: unknown format(s): <x> (choose from md, csv, pdf) Typo in validate --format. Use a comma list of md, csv, pdf.
at least one format is required (choose from md, csv, pdf) validate --format given an empty list. Name at least one format, or drop the flag for all three.

Validate and generate refusals

error: N error(s) found; exiting 1 (--no-fail to suppress) is validate doing its job: the instance carries build-aborting codes or names, listed individually above the line. Fix them in DHIS2, or --no-fail if the run must pass anyway. Validate the instance explains the grading.

Generate refuses what validate marks as build-aborting. The whole run, not the one object - skipping it would publish a broken guide quietly instead of failing loudly:

error: optionSets 'Bednet distribution' (csRsm0D7guY) has code
'ENTO - IRS < 6 Months', which carries '<'. A DHIS2 code becomes an
identifier value, which the IG publisher writes into a table cell unescaped
and then strict-parses, so the publisher aborts with "Unable to Parse HTML -
node 'td' has unexpected content" in its last pass, once every resource has
already been rendered. Change the code in DHIS2, then run `d2w fhir
validate` for the full report.

Cause: an in-scope code on an identifier surface carries <, under hostile_names = "refuse" or with the key unset. Fix: change the code in DHIS2, or set hostile_names = "substitute", which publishes the code with its comparison reworded and its spaces hyphenated, and states the DHIS2 code beside it as the dhis2-code property. Only < refuses; > and & stay warnings.

A name refuses the same way, through its own message: a DHIS2 name stays byte-true on the emitted resource's title, which the publisher writes into pages it strict-parses after writing. The refusal names the object - or the option, whose name lands in page tables - and ends with the same instruction: change the name in DHIS2, then run d2w fhir validate for the full report.

The same refusal, read off the files a build publishes:

error: 3 build-aborting artifact(s) found; exiting 1 before the publisher runs
(--no-fail to suppress)

Cause: d2w fhir check-artifacts found a < in the artifacts on disk, or in the guide's own identity. That is a different question from the two above, which read the instance and the selection - a build publishes whatever ig/fsh-generated/ and ig/input/ hold, so output from before the gate existed, output from an older toolchain pin, and hand-authored FSH all reach the publisher without passing it. Fix: what each finding's own line says, which follows from where the value came from - regenerate after narrowing the selection for a value from DHIS2, change [ig] <key> in fhir.toml and run d2w fhir init --refresh for the guide's own title, name, publisher or description, edit the file for a hand-authored one. The build refuses before it begins covers the scan.

A scan that exits 0 with warnings:

warning: 29 finding(s) the build survives; the guide publishes and what it costs
is read in the table above

Cause: those forms carry an organisation-unit assignment List naming no unit this project publishes, usually because max_level stops above the level the forms are assigned at. The build is valid, which is why it is not a refusal; what the guide publishes is forms nobody can submit a response to, and $generate answers 422 for each. Fix: raise max_level, or narrow the form selection to what the registry covers, then regenerate.

Every finding sits under fsh-generated/, right after a generate that changed posture: those findings are a stale compile, not stale sources. The sources on disk are the ones the run just wrote; ig/fsh-generated/ is SUSHI's compile of the sources before it, and the scan reads it because the publisher does. A current d2w fhir generate removes that tree whenever it rewrites a FSH source and names it in a note, so a project that reaches this state has a compile written back after the run - or a generate from a lock that predates the removal. Fix: run make sushi and scan again, or make build, which compiles first. No source edit and no rename in DHIS2 is part of the answer - the scan comes back clean once the compile is of the sources on disk.

The guide is not wrong, only old:

drift  warn  2 object(s) moved since the guide was published: ... run
`d2w fhir generate`, then `make sushi`, to publish the instance as it now stands

Cause: not a refusal. d2w fhir doctor run from a project directory compared the artifacts on disk against the instance and found objects the instance now holds inside this project's own selection that the guide does not - an organisation unit added to the registry scope, an option added to a published set, a question added to a form, a program stage that publishes none. It is a warning and exits 0: a guide describing the instance as it stood last month still serves, still captures, and still forwards. Fix: regenerate, then compile, exactly as the line says. Drift, explained covers what is compared and why tracked entity types are not. A code-sourced naming run refuses on unusable stems:

error: [generate.naming] source = "code" needs a usable, unique code on
every selected option set; 3 of the 12 selected cannot serve as identity
stems: <name> (<uid>) <defect>; ... A stem becomes a FHIR resource id, so it
takes ASCII letters, digits, hyphen and dot, 1 to 64 characters, and no two
of the selection may share one. Give those option sets such codes in DHIS2,
or set source = "code-or-id", which takes the code wherever one can serve and
the DHIS2 id on the 3 that cannot, so the run completes. `d2w fhir validate`
names every offender.

Cause: [generate.naming] source = "code" met a selected object with a missing, unusable, or colliding code. Fix: what the message says - the validate report names every offender as code-stem-refusal.

On the DHIS2 demo database every organisation unit is coded OU_<digits>, and a FHIR resource id forbids the underscore, so source = "code" refuses there on all 1,332 of them. source = "code-or-id" runs on that instance: every unit falls back to its DHIS2 id under one aggregate note, and the objects that do carry usable codes are still named by them.

A compile that stopped on an error left nothing behind:

SUSHI stopped on an error. Removed ig/fsh-generated, which held a partial
compile: the FHIR endpoint has nothing to read until a compile finishes.

Cause: SUSHI exited non-zero, and it keeps whatever it had written up to that point. That half would read as a finished guide to d2w fhir serve, d2w fhir check-artifacts and d2w fhir forward, so make sushi removes it. Fix: read SUSHI's own errors above the line, correct what they name, and compile again. The commands that read the compiled tree now refuse the project outright rather than publishing a partial one.

A program UID listed under the wrong selection table fails by name:

error: program '<name>' (<uid>) has programType WITH_REGISTRATION; a tracker
program is selected under [generate.tracker_programs], which emits one
Questionnaire per stage
error: program '<name>' (<uid>) has programType WITHOUT_REGISTRATION; a
WITHOUT_REGISTRATION program is selected under [generate.event_programs]

Cause: [generate.event_programs] selects WITHOUT_REGISTRATION programs and [generate.tracker_programs] selects WITH_REGISTRATION ones; you named a UID in the wrong table. Fix: move the UID. (With empty tables the sweep routes each program by its live type and never refuses.)

SUSHI and IG publisher failures

Symptom (literal text) Cause Fix
make setup or make upgrade stops in the publisher.jar step with curl: (92) HTTP/2 stream 1 was not closed cleanly, curl: (56) or curl: (18) The connection to GitHub's release storage dropped part way through a download of a few hundred megabytes, and the project's Dockerfile predates the resuming download. d2w fhir init --refresh to bring the Dockerfile up to date: it resumes a dropped download, up to eight attempts. A failed upgrade keeps the previous image, so make generate and make build still run meanwhile.
Sushi timeout exceeded: 1800 seconds then Process exited with an error: 143 (Exit value: 143) The publisher's internal SUSHI run overran the ig/fsh.ini timeout. Raise it: d2w fhir init --sushi-timeout <seconds> (or edit [FSH] timeout in ig/fsh.ini).
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space mid-validation, a Java stack trace, partial phases logged The ceiling is too small for the guide. This is a real build error, not a kill. Raise it - make build JAVA_HEAP=<larger> - and give docker more memory with it: the build holds about 6 GB besides the heap (the JVM's own memory, then Jekyll at the end), so docker needs the new ceiling plus that. The derived default stops at 8g for this reason, and on one 16 GB docker VM 8g completes a national guide where 4g dies here and 10g is killed at Jekyll.
The publisher exits 137 and the build reports BUILD KILLED - out of memory 128 + 9 - SIGKILL, and the container's cgroup counted an oom_kill, so this is the kernel's out-of-memory killer during the peak-memory phases. The ceiling is too large for the machine. The build prints this one in full: the ceiling, the memory docker reports, the peak reached, and the containers running when it was sampled. Stop those and run again - a publisher build wants the machine to itself - then drop the ceiling to make build JAVA_HEAP=8g if it was set above that (the JVM grows into a larger heap without needing it, and Jekyll needs about 4 GB beside it at the end), then give docker more memory (Docker Desktop: Settings > Resources > Memory; on Linux docker uses the machine's own memory). ig/output holds whatever the last completed build wrote, or is partial - the site is written last, so nothing from this run is trustworthy.
The publisher exits 137 and the build reports BUILD KILLED without the out-of-memory line A SIGKILL the kernel's out-of-memory killer did not count: a docker stop on a container ignoring SIGTERM, a docker kill, a timeout around the build. A host on cgroup v1 counts none either way. Look outside the build: a CI step timeout, a docker stop or docker kill from another terminal, a machine that slept. ig/output is in the same state as above - the last completed build's, or partial.
Publishing Content Failed: Process exited with an error: 4 (Exit value: 4) Not an exit code - SUSHI exits with the number of errors it counted, and the publisher reports it and stops. Read the Sushi: error lines above it, not the number.
Failed to register resource at path: .../input/resources/... One predefined resource failed to load - malformed JSON or a failed read; a file written shortly before the container read it can come back truncated across a Docker bind mount. Re-run first. A transient read registers cleanly the second time; a genuinely malformed resource fails every time on the same files. Cross-check Loaded virtual package sushi-local#LOCAL with N resources against the file count under ig/input/resources/.
Unable to process page .../CodeSystem-....html with Caused by: org.hl7.fhir.exceptions.FHIRFormatError: Unable to Parse HTML - node 'td' has unexpected content A DHIS2 code carrying < reached an identifier table cell - the publisher's final pass, so the whole build was spent first. Change the code in DHIS2. d2w fhir check-artifacts finds it in the file on disk before a build starts, and d2w fhir validate reports the same object as template-hostile-code from the instance side.
Unable to Parse HTML - node 'h2' has unexpected content A DHIS2 name carrying < in a change-history heading - a malformed page, not an aborted build. Change the name in DHIS2; validate reports it as template-hostile-name.
The html source has duplicate anchor Ids: <code-system-id>-<code> in the QA output, often under an Internal error in location line Two distinct DHIS2 codes differ only in whitespace (Pre eclampsia beside Preeclampsia), and the publisher's anchor slug strips it, so both concept rows get one anchor id. Cosmetic - the build completes and the page renders both rows. Regenerate under hostile_names = "substitute" and the guide carries no space-carrying code at all (Pre eclampsia is published as Pre-eclampsia, with the DHIS2 code stated beside it as a dhis2-code property), so the anchors differ and the message goes away. Under "refuse" the codes stay byte-true and so does the message: a content: complete CodeSystem must state both, so nothing is merged on this side. IG_PUBLISHER_ISSUES.md 107 carries the upstream repro.
Publishing Content Failed: Unable to process page <Resource>.html, with Caused by: org.hl7.fhir.exceptions.FHIRFormatError: Unable to Parse HTML - ... last text = '<the text before the bracket>' and AIProcessor.produceMDForResource in the stack A DHIS2 name carrying < reached a rendered page. This is the expensive one: the name survives every earlier pass, Checking Output HTML included, and kills only the publisher's final AI-markdown pass - hours in, once every resource has already been rendered, and the message names a page rather than the object. Run d2w fhir check-artifacts: it reads the same files the publisher does, names the file, the resource, and the element in seconds, and it is what make build runs first, so a refreshed project (d2w fhir init --refresh) never reaches this failure again. d2w fhir validate names the same objects from the instance side, and d2w fhir generate refuses the run up front. Rename the object in DHIS2; where you cannot - upstream demo metadata, a name a ministry actually uses - leave it out of the selection. examples/igs/refused-names is the worked exhibit.
Duplicate definition of ... The same identity reached SUSHI twice - once compiled from FSH, once as a predefined resource; generated FSH left behind by an older plugin layout. Run d2w fhir generate; it sweeps the superseded FSH and the report's deleted count is the confirmation.
One error per organisation unit with geometry during an offline build (TX_SERVER=n/a): The value provided ('application/geo+json') was not found in the value set 'MimeType' ... (error message = Cannot invoke "...TerminologyClientContext.getAddress()" because "tc" is null) The GeoJSON boundary attachment states its media type, R4 invariant att-1 requires it wherever the attachment carries data, and that field binds to the IETF BCP 13 media types - a value set only a terminology server can answer. Offline there is no server, and the publisher reports the null terminology client as the reason. The build completes; the errors are the whole cost. Build online and they go away. Offline is still worth having: on a district registry it is a 51-second build, and dropping the media type to silence these would trade them for one att-1 violation per unit on every build, online ones included.
A build that sits at Generating Narratives far longer than the resource count explains Not slow - idle. Every ConceptMap row is validated against the system its target code sits in, and a DHIS2 identifier namespace declared only as a NamingSystem answers nothing, so the publisher asks the terminology server about each row in turn and is told UNKNOWN_CODESYSTEM each time. Measured on one district-scale guide: 4,779 terminology requests, 57 percent of them byte-identical repeats, and the narrative phase alone at 438 seconds. Regenerate with a current d2w fhir generate. It publishes each of those namespaces as a content: complete CodeSystem beside the maps, which drops the same guide to 5 terminology requests and 1.5 seconds of narratives. content: not-present does not work - the publisher reads it as "the codes are elsewhere" and asks anyway.
A build whose Generate Native Outputs phase runs for minutes on macOS Not the publisher - the mount. Docker reaches a host directory over a network-style filesystem, and that phase writes tens of thousands of small files one at a time. Measured on one guide: 341 seconds through the mount, 21 seconds on the container's own disk. Nothing to do on a refreshed project: make build streams the project into the container, builds there, and streams output/, fsh-generated/ and input-cache/ back. d2w fhir init --refresh brings an older Makefile up to date. make build-bind is the old behaviour if you want to watch output/ fill as it is written.

Serve refusals

The facade itself is Serve the IG; these are the ways it refuses to start.

Symptom (literal text) Cause Fix
error: no compiled IG at ig/fsh-generated/resources - run `d2w fhir generate`, then `make sushi` in the project, and serve again. The default mode serves what SUSHI wrote, and this project has never been compiled. In a guide depending on a registry package, the message also names the registry build the compile waits on. What the message says - or d2w fhir serve --live to serve straight from the instance, no compile needed.
error: port 8391 on 127.0.0.1 is already in use (usually the local DHIS2 instance; set [serve] port in fhir.toml or pass --port) Something else holds the address - typically a local DHIS2 stack on 8080. Set [serve] port in fhir.toml, or --port.
No refusal, and d2w fhir serve starts on a port your local DHIS2 already answers on The probe binds an IPv4 socket and the other listener holds the port on IPv6 only. Docker Desktop on macOS publishing 8080 is exactly that (TCP *:8080 (LISTEN), IPv6), so serve starts beside DHIS2 and then answers some of the localhost:8080 requests meant for it. Choose the port in [serve] rather than relying on the probe. lsof -nP -iTCP:<port> -sTCP:LISTEN shows who really holds it.
`d2w fhir serve` needs the dhis2w-fhir-serve package. Install it with `uv add dhis2w-fhir-serve` or `pip install 'dhis2w-cli[serve]'` The serve package is an extra, and this environment does not have it. A scaffolded project declares it, so uv sync there is enough. Install it either way the message names.
error: `--ui` needs a built frontend at .../dhis2w_fhir_serve/static, and there is none. Build it with `make ui` (an installed wheel ships it already). Running --ui from a source checkout that never built the frontend bundle. make ui in the checkout; installed wheels ship the bundle.
error: the capture UI bundle at .../dhis2w_fhir_serve/static is older than the frontend source - it was built from <fingerprint> and the source now reads <fingerprint>. Run `make ui` to rebuild it. A checkout whose frontend source moved since the bundle was built - a pull, a branch, or an edit of your own. The browser would otherwise run the older JavaScript with nothing saying so. make ui. Only a checkout is graded this way; an installed wheel carries no frontend source to compare against.

Forward outcomes

d2w fhir forward (Forward captures into DHIS2) is a dry run by default - nothing is written, nothing moves. Its closing lines are outcomes, not crashes:

Symptom (literal text) Cause Fix
error: no compiled IG at <dir>/ig/fsh-generated/resources - run `d2w fhir generate` and then `make sushi` in the project, then run this command again. Translation reads the compiled artifacts, there are none, and this project states [forward] live = false so no stand-in is built off the instance. Generate and compile, then forward again - or drop live = false and let the drain build the guide off the instance.
error: N response(s) rejected by DHIS2 where the rollup names E1300 Generated by ProgramRule (...) A DHIS2 program rule on the instance refused a value. Synthetic corpora hit this often: a load set draws values inside a data element's own value type, and a program rule can forbid a subset of that range. Read the rule the message names in the instance's Maintenance app. This is a fact about that instance's configuration, and a load set is not the data to relax a rule for.
note: the spool is empty - `d2w fhir serve` is what fills it Nothing has been captured; .serve/responses/received/ holds no receipts. Run the facade, capture something (or post a load set), then forward.
error: N response(s) rejected by DHIS2; exiting 1 - read the import summary, fix the instance or the data, and forward again DHIS2's import refused the payloads; each receipt moved to rejected/ beside its import report. Common codes: E1029 (unit outside the form's assignment), E8023 (missing attribute option combo), E8025 (a combo whose category options are not available at that organisation unit), E1064 (duplicate unique attribute value). Read reports/fhir-forward-report.md and the per-receipt reports; fix, then forward again.
note: N response(s) this dry run could not check - each is a stage event whose enrollment a registration of the same run creates, and only an import creates it A dry run writes nothing, so the enrollment a registration mints is not there when the stage event naming it is validated; DHIS2 answers that event E1313 plus the E1079 program mismatch it asserts against the absent enrollment. Counted unverifiable, not rejected, and the run still exits 0. Nothing to fix - --import posts registrations first and the pair does not arise. A stage event whose enrollment no registration of the run mints is a rejection instead, and says so.
note: N response(s) sent M value(s) an earlier submission had already sent ..., or on a dry run note: N response(s) carry M value(s) an earlier submission has already sent ... Not an error. A receipt this project already forwarded had sent the same aggregate values - same data element, category option combo, period, organisation unit, and attribute option combo - and DHIS2 replaces such a value in place while counting the write exactly as it counts a first entry. Nothing, if the second submission is the correction you meant. If it is not, read the earlier submission at .serve/responses/forwarded/<id>.json and capture the form again with the value you want. Values a previous submission already sent explains the reading.
note: N response(s) were not sent: each carries M value(s) in all that a receipt this spool has already forwarded sent, and `[forward] overwrites` is `refuse` ... Not an error, and not a failure of the responses. This project states [forward] overwrites = "refuse", so a form carrying a figure an earlier submission already sent is refused whole and left in the queue with the covered figures written down beside it. Read them, then decide: d2w fhir forward --import --overwrites allow sends them and names every figure replaced, or leave them queued and correct the earlier submission instead. Overwrites carries the posture in full.
note: N receipt(s) DHIS2 has already accepted record no values, so this run cannot say whether they sent any of these values first A receipt in forwarded/ has an import report naming no values, which every receipt a drain files does record. Something other than a drain put it there - a hand-copied file, an edited report. Restore the report the drain wrote, or accept that those receipts are invisible to the reading above. Nothing else in the run is affected.
note: N response(s) refused by the translator - they stay in the spool, so fixing the guide or the data and forwarding again is the retry The translator could not build a payload it stands behind; the receipts stayed in received/. Fix the guide or the data; forwarding again is the retry.
note: <file> does not read as a receipt and was moved to .serve/responses/malformed/: ... A spool file is not a stored response envelope - hand-edited, truncated, or foreign. The run moved it aside and carried on with everything else, so one bad file costs one receipt rather than the drain. Read .serve/responses/malformed/<file>.reason.json, then restore the receipt from wherever it came from, or delete it. d2w fhir spool --details lists the whole holding pen.
error: another drain of this spool is running: process N holds .serve/responses/.drain.lock ... A second d2w fhir forward started while one was already draining this project. Two drains would post every payload twice and race each other's renames, so the second one fails rather than waits. Wait for the running drain and forward again. If no such process exists - a machine that lost power mid-drain - delete the named lockfile.
note: <id>: <path> was gone when the drain went to file it ... Something moved a receipt's file between the read that listed it and the rename that would have filed it. DHIS2 had already answered about the payload, and that answer is in the report. Nothing to fix in the run - it graded the receipt rather than throwing the drain away. Check whether a second operator or a hand-run mv is working in the same spool.
A receipt reporting itself entered-in-error sits in rejected/ with a report naming no DHIS2 error Withdrawal is a deletion and this toolchain imports, so that response can never convert - no change to the guide and no change to the instance would help. It is filed rather than retried by every drain. See Corrections and withdrawals. Nothing, usually. d2w fhir requeue <id> puts it back in the queue if you want it tried again.
DHIS2 refuses a load-set re-import with E1002 and E1080 A load-set corpus mints the DHIS2 identities it names, so it imports once - those UIDs now exist. d2w fhir generate load-set --salt <anything> mints a fresh corpus; the same salt reproduces the same corpus.
DHIS2 refuses a receipt you moved back out of forwarded/ and forwarded again, naming a UID it already holds The receipt already imported. An event's UID is derived from the receipt's own logical id and every payload is posted as a create, so a second forward of one receipt names the objects the first one made. This is the refusal working - the visit is already in DHIS2. Look the named UID up rather than forwarding again; the receipt belongs in forwarded/.

Next: the series index