nektos/act · error

expected format {owner}/{repo}/.github/workflows/{filename}@

Error message

expected format {owner}/{repo}/.github/workflows/{filename}@{ref}. Actual '%s' Input string was not in a correct format

What it means

For a job-level 'uses: {owner}/{repo}/.github/workflows/{file}@{ref}' (reusable workflow called remotely), newRemoteReusableWorkflow parses the string; if it returns nil the format is wrong and act returns this error listing the expected shape. The parser requires exactly owner/repo(/subpath)/.github/workflows/filename@ref over HTTPS-style GitHub references.

Source

Thrown at pkg/runner/reusable_workflow.go:28

	"path"
	"regexp"
	"sync"

	"github.com/nektos/act/pkg/common"
	"github.com/nektos/act/pkg/common/git"
	"github.com/nektos/act/pkg/model"
)

func newLocalReusableWorkflowExecutor(rc *RunContext) common.Executor {
	return newReusableWorkflowExecutor(rc, rc.Config.Workdir, rc.Run.Job().Uses)
}

func newRemoteReusableWorkflowExecutor(rc *RunContext) common.Executor {
	uses := rc.Run.Job().Uses

	remoteReusableWorkflow := newRemoteReusableWorkflow(uses)
	if remoteReusableWorkflow == nil {
		return common.NewErrorExecutor(fmt.Errorf("expected format {owner}/{repo}/.github/workflows/{filename}@{ref}. Actual '%s' Input string was not in a correct format", uses))
	}

	// uses with safe filename makes the target directory look something like this {owner}-{repo}-.github-workflows-{filename}@{ref}
	// instead we will just use {owner}-{repo}@{ref} as our target directory. This should also improve performance when we are using
	// multiple reusable workflows from the same repository and ref since for each workflow we won't have to clone it again
	filename := fmt.Sprintf("%s/%s@%s", remoteReusableWorkflow.Org, remoteReusableWorkflow.Repo, remoteReusableWorkflow.Ref)
	workflowDir := fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(filename))

	if rc.Config.ActionCache != nil {
		return newActionCacheReusableWorkflowExecutor(rc, filename, remoteReusableWorkflow)
	}

	return common.NewPipelineExecutor(
		newMutexExecutor(cloneIfRequired(rc, *remoteReusableWorkflow, workflowDir)),
		newReusableWorkflowExecutor(rc, workflowDir, fmt.Sprintf("./.github/workflows/%s", remoteReusableWorkflow.Filename)),
	)
}

View on GitHub (pinned to 4f41128141)

Solutions

  1. Rewrite the job 'uses:' as owner/repo/.github/workflows/filename.yml@ref, e.g. uses: org/repo/.github/workflows/build.yml@main.
  2. For same-repo calls use the local form: uses: ./.github/workflows/build.yml.
  3. Ensure the filename includes .yml/.yaml and the ref is a branch, tag, or full sha.

Example fix

# before (workflow)
jobs:
  deploy:
    uses: org/repo/workflows/deploy.yml

# after
jobs:
  deploy:
    uses: org/repo/.github/workflows/deploy.yml@v2
Defensive patterns

Strategy: validation

Validate before calling

# regex check for remote reusable workflow uses
python3 - <<'EOF'
import re,glob,yaml
pat=re.compile(r'^[^/]+/[^/]+/.*/\.github/workflows/[^/]+@(refs/)?\S+$')
for f in glob.glob('.github/workflows/*.y*ml'):
    for jid,job in (yaml.safe_load(open(f)).get('jobs') or {}).items():
        uses=job.get('uses')
        if uses and not uses.startswith('./') and not uses.startswith('docker://'):
            assert pat.match(uses), f'{f} job {jid}: bad reusable workflow uses: {uses!r}'
print('reusable uses ok')
EOF

Type guard

func isRemoteReusableWorkflowRef(uses string) bool {
    i := strings.Index(uses, "/.github/workflows/")
    at := strings.LastIndex(uses, "@")
    return i > 0 && at > i && at < len(uses)-1
}

Prevention

When it happens

Trigger: A job with 'uses:' that is not a remote reusable workflow path: missing '@ref', missing '.github/workflows/' segment, a local './' path routed to the remote parser, spaces, or a 'docker://'-style reference.

Common situations: Converting a local reusable workflow call ('uses: ./.github/workflows/x.yml') and breaking the path; forgetting the @ref; pointing at a file outside .github/workflows.

Related errors


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/54f80d8d427b8af9. Report an issue: GitHub.