Invalid input, secrets is not defined in the referenced workflow A developer documented a GitHub Actions failure mode in which a reusable-workflow call is rejected before any job starts with the annotation "Invalid input, secrets is not defined in the referenced workflow." The error typically stems from a `secrets:` line indented one level too deep into the `with:` block, where it is parsed as an input name rather than a job key; the fix is to move the key out one level to align with `uses:` and `with:`. The writeup also distinguishes this from the one-word-different "Invalid secret" error, which flags an undeclared secret name passed by a caller. Invalid input, secrets is not defined in the referenced workflow is the input check rejecting a key named secrets that it found where input names are read, which is what a secrets: line does when it is indented one level too deep and lands inside with: . There is a second message one word away, Invalid secret , and that word is the fastest diagnosis on the page: it names which of the two checks gave up, and therefore which file you should have open. The grid on the right is the table reproduced in the body of this page. The annotation is quoted in full from pytorch/torchchat 1351. The run is rejected before any job starts. The Actions tab holds a run with no jobs and one annotation against a line in the calling workflow, carrying a line and a column number, and the pull request shows a check that never reports rather than one that went red. What makes this one confusing is the wording: the annotation says Invalid input while the key on the line it points at is called secrets , so the usual next move is to go hunting for a secret that does not exist. There is none to find. Another job in the same file, calling the same workflow, will often validate perfectly, because its secrets: line is one indent further left. Actions annotation, quoted from pytorch/torchchat 1351 Invalid workflow file: .github/workflows/run-readme-periodic.yml L50 The workflow is not valid. .github/workflows/run-readme-periodic.yml Line: 50, Col: 16 : Invalid input, secrets is not defined in the referenced workflow. Common causes The secrets key is indented into the with block The cause in the quoted annotation, and in our experience the usual one when the name in the message is secrets . One extra level of indentation moves the key out of the job and into the input map, where it is read as an input name. The value and the spelling are untouched, so the line is correct in isolation and reviewers read straight past it. Another scalar job key was pulled in by the same edit Reindenting a block moves everything under it. if: and name: carry scalars and clear the schema the way secrets: inherit does, so either landing inside with: produces this message with its own name in it. Keys carrying a mapping, such as permissions: or concurrency: , never reach this check, because with accepts only scalar values. The caller passes an input the called workflow never declared The same message from the same check, with nothing to do with secrets: the key really is an input and no declaration matches it. A rename on either side does it, and catalyst/catalyst-moodle-workflows 159 is a public report of an input dropped from a shared workflow taking a caller in another repository down with it. The other direction, which is a different string A caller that passes secrets by name rather than inheriting is checked against on.workflow call.secrets in the called workflow, and an unmatched name is reported as Invalid secret, NAME is not defined in the referenced workflow. One word from the message on this page, and a fix in the other file. How to fix it Read the column number, then move the key 1. Take the line and column from the annotation. The column lands on the value, not the key, so on secrets: inherit it points at the first letter of inherit . 2. Look at what that line is nested under. secrets: belongs on the job, indented the same as uses: and with: , never among the entries inside it. 3. Move it out one level and leave the value alone. Nothing else about the call changes, and nothing has to be declared. 4. Check the other calling jobs in the file before you push, since a reindent rarely touches only one. .github/workflows/periodic.yml, corrected illustrative jobs: test-quantization-any: uses: ./.github/workflows/linux-job.yml secrets: inherit with: runner: linux.g5.4xlarge.nvidia.gpu gpu-arch-type: cuda Everything else a calling job may carry sits beside with: , not in it, and GitHub publishes the closed set: "When you call a reusable workflow, you can only use the following keywords in the job containing the call". Those keys are name , uses , with , secrets , strategy , needs , if , concurrency and permissions , the same nine properties the workflow schema gives a calling job. Anything on that list is a sibling of uses: ; anything that is neither on it nor a declared input has no place on that job. .github/workflows/release.yml illustrative jobs: release: name: Release needs: build if: github.ref == 'refs/heads/main' permissions: contents: read uses: ./.github/workflows/deploy.yml with: target: production secrets: inherit Read the declared inputs before adding a key to with When the key really is an input, the legal names are in the called workflow under on.workflow call.inputs , at the ref your uses: line pins. The syntax reference puts the obligation on the caller: "The identifier must match the name of an input defined by on.workflow call.inputs.