All things Shopify and commerce
We're moving the community! Starting July 7, the current community will be read-only for approx. 2 weeks. You can browse content, but posting will be temporarily unavailable. Learn more
I'm using RemixJS, the latest versions of @Shopify/shopify-app-remix
I first noticed this error when the app reviewer declined my app since I didn't have proper "Upgrade/Downgrade" buttons. I was very confused since this works flawlessly on the test store. I even provided a full video of it working, twice.
After debugging logs, I couldn't find ANYTHING.
I have two plans declared on my "shopify.server.ts". under the billing object which are available on "availablePlans". and "isBillingTest()" just checks my .env variable for TEST_BILLING === 'true'
"test: false" in this case right now.
When I click "Subscribe", my code executes here:
export const action = async ({ request }: ActionFunctionArgs) => { const adminContext = await authenticate.admin(request); const { billing, session } = adminContext; const { hasActivePayment, appSubscriptions } = await billing.check({ plans: availablePlans, isTest: isBillingTest(), }); if (!hasActivePayment) { try { await billing.require({ plans: availablePlans, onFailure: async (error) => { console.error('Billing require failed:', error); console.log('Attempting to redirect to billing page for plan:', plan); return billing.request({ plan: plan.toString() as PlanName, isTest: isBillingTest(), returnUrl: createReturnUrl(session.shop), }); }, }); } catch ( error ) { console.log('error billing', error ); } }
and this is the error:
Response { size: 0, [Symbol(Body internals)]: { body: null, type: null, size: 0, boundary: null, disturbed: false, error: null }, [Symbol(Response internals)]: { url: undefined, status: 401, statusText: 'Unauthorized', headers: { 'x-shopify-api-request-failure-reauthorize-url': 'https://xxxxxx.myshopify.com/admin/charges/123345/21345/RecurringApplicationCharge/confirm_recurring_application_charge?signature=BAh7BzoHaWRsKwg' }, counter: 0, highWaterMark: undefined } }
It's very weird. Why am I getting 401 errors? I wonder if this what the reviewer ran into too.
Although, when I change test: true then I can make successful tests.
Any ideas would be greatly appreciated.
Here is another clue for the Shopify team: On this app, I always had it set to billing test: false. I decided to run a "test payment" (because I'm like "why was the reviewer getting an error? Maybe something on production?), so I changed test: true. Subscription worked. No issues. Webhooks ran.
I then changed it BACK to test: false. I go to subscribe, and I'm expecting it to redirect to the charges URL, but no, 401. This error only started happening AFTER I changed it from the original test: false -> true -> false.
Now, I don't know what else to do. I'm afraid the reviewer is going to look again and say it failed. This seems to be on the Shopify side I'm assuming. If I manually enter that URL from the response "x-shopify-api-request-failure-reauthorize-url" then it does go to the Approval Page.
Here is the Shopify App Reviewer getting a 401. This is from my server logs. Redacted information.
[shopify-app/INFO] Requesting billing | {shop: 1234.myshopify.com, plan: Starter Plan, isTest: false, returnUrl: https://admin.shopify.com/store/1234/apps/my-app/app/billing} POST /app/billing?_data=routes%2Fapp.billing 401 - - 735.172 ms
But somehow after this the webhook ran for subscription? How is this possible if they didn't get redirected to an approval page?
app subscription { admin_graphql_api_id: 'gid://shopify/AppSubscription/1234', name: 'Pro Plan', status: 'ACTIVE', admin_graphql_api_shop_id: 'gid://shopify/Shop/1234', created_at: '2025-07-03T20:35:51+08:00', updated_at: '2025-07-03T20:35:57+08:00', currency: 'USD', capped_amount: null, price: '49.00', interval: 'every_30_days', plan_handle: null } POST /webhooks/app/subscriptions_update 200 - - 290.793 ms