Decap CMS Local Proxy returns 404 error for valid GitHub API path

I’m facing an issue with my Decap CMS setup using a local proxy to link with a private GitHub repository. Whenever I attempt to publish a new entry via the CMS interface, I consistently run into messages like ‘Failed to load entry’ or ‘API Error,’ and the console shows a 404 Not Found status from the GitHub API.

Details of the Issue:
Despite confirming that both the repository and the folder are real, as well as ensuring my access token has the necessary permissions, I still receive a 404 status when trying to load media or create content.

Error Logs:
Here are some logs from my server highlighting the 404 status for requests made to get media and save entries:

Token confirmation: ghp_1...kphmC
Action: getMedia
Fetching from: https://api.github.com/repos/random-user/random-repo/contents/assets/uploads?ref=main
Status: 404 Not Found

Action: persistEntry
Fetching from: https://api.github.com/repos/random-user/random-repo/contents/news/entry.md
Status: 404 Not Found
Error response: {"message":"Not Found","documentation_url":"https://docs.github.com/rest","status":"404"}

Here are my setup files:

CMS configuration:

backend:
  name: proxy
  proxy_url: http://localhost:3000/api/github
  branch: main

media_folder: "assets/uploads"
public_folder: "/assets/uploads"

collections:
  - name: "posts"
    label: "Posts"
    folder: "news"
    create: true
    fields:
      - {label: "Title", name: "title", widget: "string"}
      - {label: "Body", name: "body", widget: "markdown"}

Proxy server:

require('dotenv').config();

const express = require('express');
const path = require('path');
const apiHandler = require('./api/github.js');

const app = express();
const port = 3000;

app.use(express.json());
app.use('/api/github', apiHandler);
app.use(express.static(path.join(__dirname, 'public')));
app.get('/*', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.listen(port, () => {
  console.log(`✅ Server is working! Listening at http://localhost:${port}`);
});

API Handler:

const fetch = require("node-fetch");

module.exports = async (req, res) => {
  const { action, params } = req.body;
  let githubUrl = `https://api.github.com/repos/random-user/random-repo`;

  if (action === 'entriesByFolder') {
    githubUrl += `/contents/${params.folder}?ref=${params.branch}`;
  } else if (action === 'getEntry') {
    githubUrl += `/contents/${params.path}?ref=${params.branch}`;
  } else if (action === 'getMedia') {
    githubUrl += `/contents/${params.mediaFolder}?ref=${params.branch}`;
  } else if (action === 'persistEntry') {
    const file = params.dataFiles[0];
    githubUrl += `/contents/${file.path}`;
  }

  // Additional logic for fetch and response handling here
};

Although my token works when tested independently with curl, and I’ve confirmed the repository structure is correct with all necessary folders present, I can’t figure out why I’m getting 404 errors every time I try to access the private repository through the proxy.

i had that same problem! turns out my token was missing the ‘repo’ scope too. it worked fine with curl but decap needed full access. make sure to check your token scopes in github settings under dev > personal access tokens.

Check your repo visibility settings and org permissions if it’s an org repo. I hit similar 404s when my token had the right scopes but the org had extra restrictions turned on. Also make sure your proxy isn’t messing with the auth headers - sometimes it strips the token during forwarding. Add some debug logging to see if the Authorization header with your Bearer token is actually reaching GitHub. And double-check you’re using the right repo name format, especially if there are special characters or you renamed it recently.

Sounds like a folder timing issue in your private repo. I’ve hit the same 404s when Decap tries to access folders that don’t exist on main yet. Your news and assets/uploads directories need to actually exist in the repo before the CMS can write to them. Drop empty .gitkeep files in both folders and push to main first. Also check if your proxy’s mangling the auth - log the actual Authorization header it’s sending. Tokens get corrupted during proxy forwarding all the time, especially with middleware parsing problems. Test your API endpoints directly in Postman with the same token to make sure they work outside the proxy.

your api handler’s missing the fetch logic and auth headers. you’ve built the url but there’s no authorization header or fetch call with the token. add headers: { 'Authorization': 'token your_github_token' } to your fetch request.