| name | fix-docker-image-org-mismatch |
| description | Fix Docker GHCR push failures when repository organization changes but IMAGE\_NAME remains hardcoded to old org |
| category | ci-cd |
| date | "2026-02-09T00:00:00.000Z" |
| tags | ["docker","ghcr","github-actions","authentication","organization-migration"] |
| user-invocable | true |
Fix Docker Image Organization Mismatch
Overview
| Field | Value |
|---|
| Date | 2026-02-09 |
| Objective | Fix Docker Build workflow failure after repository transfer to new GitHub organization |
| Root Cause | IMAGE_NAME hardcoded to old org while GITHUB_TOKEN scoped to new org |
| Outcome | ✅ All Docker images successfully pushed to GHCR under correct organization |
| Issue | PR #3123 - Docker CI failure on HomericIntelligence/Odyssey |
When to Use This Skill
Primary Trigger: Docker workflow fails with GHCR push errors after repository org change
Specific Indicators:
- Error message:
could not parse reference: ghcr.io/{OldOrg}/{repo}:tag
- Error message:
unable to parse registry reference
- Docker build succeeds but push to GHCR fails with authentication error
- Repository was recently transferred to a new GitHub organization
- GITHUB_TOKEN scope shows different org than IMAGE_NAME in workflow
Example Error:
[0000] ERROR could not determine source: errors occurred attempting to resolve 'ghcr.io/mvillmow/Odyssey:main':
- docker: could not parse reference: ghcr.io/mvillmow/Odyssey:main
- oci-registry: unable to parse registry reference="ghcr.io/mvillmow/Odyssey:main"
Problem Background
Why This Happens
When a repository is transferred to a new GitHub organization:
- GitHub workflows automatically get a
GITHUB\_TOKEN scoped to the new org
- Hardcoded
IMAGE\_NAME variables still reference the old org
- Docker tries to push to
ghcr.io/old-org/repo using a token for new-org
- GHCR rejects the push due to permission mismatch
Key Constraint
Docker image names MUST be lowercase, but github.repository preserves the
original repository name case (e.g., HomericIntelligence/Odyssey). This
causes failures in tools that manually construct Docker image references.
Verified Workflow
1. Identify All Hardcoded Image Names
Search for hardcoded org references in Docker-related files:
grep -r "IMAGE\_NAME" .github/workflows/
grep -r "ghcr.io" .github/workflows/
grep -r "REPO\_NAME\|IMAGE\_NAME" justfile Makefile 2>/dev/null
Files to check:
.github/workflows/docker.yml
.github/workflows/release.yml
justfile or Makefile
- Any Docker Compose files
2. Update Workflow IMAGE_NAME
Fix Pattern: Replace hardcoded org with lowercase new org name
env:
REGISTRY: ghcr.io
IMAGE\_NAME: oldorg/projectname
IMAGE\_NAME: neworg/projectname
Critical: Image name must be all lowercase for Docker/GHCR compatibility.
3. Update Release Workflow
If you have a separate release workflow, add IMAGE\_NAME env var at job level:
jobs:
publish-docker:
runs-on: ubuntu-latest
env:
IMAGE\_NAME: neworg/projectname
steps:
- name: Build and push
uses: docker/build-push-action@v6
with:
tags: |
ghcr.io/${{ env.IMAGE\_NAME }}:${{ needs.validate-version.outputs.version }}
ghcr.io/${{ env.IMAGE\_NAME }}:latest
Replace:
ghcr.io/${{ github.repository }} → ghcr.io/${{ env.IMAGE\_NAME }}
4. Update Build System References
If using Justfile or Makefile:
# justfile
REGISTRY := "ghcr.io"
# BEFORE:
REPO\_NAME := "oldorg/oldreponame"
# AFTER:
REPO\_NAME := "neworg/projectname" # lowercase
5. Run Pre-commit and Verify
just pre-commit-all
grep -r "oldorg/projectname\|oldorg/oldreponame" \
--include="*.md" --include="*.yml" --include="*.toml" .
grep -r "/home/olduser" --include="*.md" --include="*.py" --include="*.sh" .
6. Commit and Create PR
git add .github/workflows/docker.yml \
.github/workflows/release.yml \
justfile
git commit -m "fix(ci): update IMAGE\_NAME for new organization
- Update IMAGE\_NAME from oldorg to neworg
- Fix GHCR push authentication failures
- Ensure lowercase image names for Docker compatibility
Fixes Docker Build workflow where GITHUB\_TOKEN scoped to
new org could not push to old org's GHCR.
"
gh pr create \
--title "fix(ci): update Docker image org references" \
--body "Fixes GHCR push failures after org transfer" \
--label "ci-cd"
7. Verify Docker Build Success
After PR is merged:
gh run list --workflow="Docker Build and Publish" --branch main --limit 1
gh run view <run-id>
gh run view <run-id> --log | grep "pushing manifest"
Failed Attempts
| Attempt | Why It Failed | Lesson Learned |
|---|
Used ${{ github.repository }} directly in tags | Preserves case (e.g., OrgName/Repo), Docker requires lowercase | Always use explicit lowercase IMAGE_NAME env var |
| Only updated docker.yml, missed release.yml | Release workflow still used old org, failed on releases | Search all workflows, not just primary Docker workflow |
| Forgot to update Justfile REPO_NAME | Local just docker-build commands failed | Check all build system files (Just, Make, scripts) |
Tried ${{ github.repository_owner }} | Still case-sensitive, doesn't include repo name | Hardcode full org/repo in lowercase |
| Re-ran failed jobs immediately | Flaky Mojo tests caused false failures | Wait for full workflow completion before judging success |
Results & Parameters
Successful Configuration
docker.yml:
env:
REGISTRY: ghcr.io
IMAGE\_NAME: HomericIntelligence/Odyssey
release.yml:
jobs:
publish-docker:
env:
IMAGE\_NAME: HomericIntelligence/Odyssey
steps:
- name: Build and push
with:
tags: |
ghcr.io/${{ env.IMAGE\_NAME }}:${{ version }}
ghcr.io/${{ env.IMAGE\_NAME }}:latest
justfile:
REGISTRY := "ghcr.io"
REPO\_NAME := "HomericIntelligence/Odyssey"
Verification Results
✅ All Docker jobs passed:
- build-and-push (production): 4m34s ✅
- build-and-push (runtime): 6m18s ✅
- build-and-push (ci): 3m41s ✅
- security-scan: 1m18s ✅
- test-images: 1m47s ✅
✅ Images successfully pushed:
ghcr.io/HomericIntelligence/Odyssey:main
ghcr.io/HomericIntelligence/Odyssey:main-ci
ghcr.io/HomericIntelligence/Odyssey:main-prod
- Plus SHA-tagged variants
Performance Impact
- No performance impact - purely configuration fix
- Build times remain the same
- Authentication now works correctly with GITHUB_TOKEN
Additional Context
Common Pitfall: Case Sensitivity
Docker image names must be lowercase, but GitHub variables preserve case:
github.repository → HomericIntelligence/Odyssey (mixed case) ❌
IMAGE\_NAME → HomericIntelligence/Odyssey (lowercase) ✅
Related Issues
This fix also addresses:
- SBOM generation failures (anchore/sbom-action uses image name)
- Security scanning failures (Trivy uses image name)
- Image testing failures (test-images job needs correct reference)
Scope of Changes
Typical files to update:
.github/workflows/docker.yml (primary)
.github/workflows/release.yml (if exists)
justfile or Makefile (local builds)
- Documentation references to old GHCR URLs
Cross-Repository Applicability
This skill applies to any repository that:
- Uses GitHub Actions to build Docker images
- Pushes to GitHub Container Registry (GHCR)
- Was transferred to a new organization
- Has hardcoded IMAGE_NAME or REPO_NAME variables
Generic workflow pattern (adapt to your repo):
env:
REGISTRY: ghcr.io
IMAGE\_NAME: <new-org>/<repo-name>
Verified On
| Project | Context | Details |
|---|
| Odyssey | PR #3123 - Docker CI fix after org transfer | notes.md |
References