Shopify auth error, unable to get auth to work

Topic summary

A developer is encountering an authentication error when implementing Shopify OAuth in a Koa.js application. The specific error message is “TypeError: request.headers.entries is not a function or its return value is not iterable” occurring during the OAuth process.

Technical Setup:

  • Using @shopify/shopify-api package with Koa framework
  • Implementing offline OAuth flow with MemorySessionStorage
  • Configuration includes API credentials, scopes, and embedded app settings

Key Issue:
The error suggests a compatibility problem between the Shopify API library’s expected request format and what Koa provides. The request.headers.entries method appears to be missing or incompatible.

Code Structure:
The implementation includes two routes:

  • /auth - initiates OAuth flow
  • /auth/callback - handles OAuth callback

Both routes pass ctx.req and ctx.res as raw request/response objects to Shopify API methods.

Status: The issue remains unresolved with no responses yet. This appears to be an adapter compatibility issue between Koa’s context object and the Shopify API library’s expectations for Web API standard request objects.

Summarized with AI on November 9. AI used: claude-sonnet-4-5-20250929.

hi,

below is my code, i am getting the following error,

Auth Error

[shopify-api/INFO] Beginning OAuth | {shop: ********.myshopify.com, isOnline: false, callbackPath: /auth/callback}
Error during /auth: TypeError: request.headers.entries is not a function or its return value is not iterable

please advise what am i doing wrong.

const Koa = require(‘koa’);
const Router = require(‘koa-router’);
const views = require(‘koa-views’);
const serve = require(‘koa-static’);
const path = require(‘path’);
require(‘@shopify/shopify-api/adapters/web-api’);
const { shopifyApi, LATEST_API_VERSION } = require(‘@shopify/shopify-api’);
const { MemorySessionStorage } = require(‘@shopify/shopify-app-session-storage-memory’);
const dotenv = require(‘dotenv’);

dotenv.config();

const app = new Koa();
const router = new Router();

const shopify = shopifyApi({
apiKey: process.env.SHOPIFY_API_KEY,
apiSecretKey: process.env.SHOPIFY_API_SECRET,
scopes: process.env.SHOPIFY_SCOPES.split(‘,’),
hostScheme: “https”,
hostName: process.env.SHOPIFY_HOST.replace(/^https:///, ‘’),
apiVersion: LATEST_API_VERSION,
isEmbeddedApp: true,
sessionStorage: new MemorySessionStorage(),
level: “debug”,
});

router.get(‘/auth’, async (ctx) => {
try {
const sanitizedShop = shopify.utils.sanitizeShop(ctx.query.shop, true);

const redirectUrl = await shopify.auth.begin({
shop: sanitizedShop,
callbackPath: ‘/auth/callback’,
isOnline: false,
rawRequest: ctx.req,
rawResponse: ctx.res,
});

if (!redirectUrl) {
throw new Error(‘Failed to get redirect URL from Shopify API’);
}

console.log(‘Redirect URL:’, redirectUrl);
ctx.redirect(redirectUrl);
} catch (error) {
console.error(‘Error during /auth:’, error);
ctx.status = 500;
ctx.body = ‘Auth Error’;
}
});

router.get(‘/auth/callback’, async (ctx) => {
try {

const session = await shopify.auth.callback({
rawRequest: ctx.req,
rawResponse: ctx.res,
query: ctx.query,
});

console.log(‘Access Token:’, session.accessToken);
console.log(‘Shop Name:’, session.shop);
console.log(‘Session ID:’, session.id);

await shopify.sessionStorage.storeSession(session);

ctx.redirect(/?shop=${session.shop});
} catch (error) {
console.error(‘Error during auth callback:’, error);
ctx.status = 500;
ctx.body = ‘Auth Callback Error’;
}
});

router.get(‘/’, async (ctx) => {
await ctx.render(‘app’, {
apiKey: process.env.SHOPIFY_API_KEY,
shop: ctx.query.shop
});
});

app.use(serve(path.join(__dirname, ‘public’)));

app.use(views(path.join(__dirname, ‘views’), {
extension: ‘ejs’
}));

app.use(router.routes()).use(router.allowedMethods());

app.listen(3060, () => {
console.log(‘App listening at http://localhost:3060’);
});