First things to check
Before diagnosing anything specific, run these four. Most weirdness resolves at one of these:
- Is the device online? Look at your phone's wifi/cell indicator. If you're offline, sales queue locally and sync when you reconnect; reports won't refresh from the backend. Get on a network if you can.
- Is the sync chip clear? The leftmost chip in the top strip shows pending sync state. If it shows a number, you have queued operations waiting to send. Tap it to see what's pending; the queue drains automatically when you're online. Don't post end-of-event inventory until the queue is empty.
- Have you pulled recently? Settings → Pull from Backend Now. Brings down the latest catalog, events, categories, bundles, and settings. Many "I edited the sheet but the app doesn't see it" issues are just a missing pull.
- Is the right event active? Tap the middle chip in the top strip. If it shows the wrong event (or "Test Event" when you meant to be on a real one), pick the right one before ringing sales.
Authorization warnings
I ran a function and got a yellow "Google hasn't verified this app" warning
This is normal and expected. Apps Script shows it any time a script needs permission for a capability it doesn't already have. You'll see it during initial setup (the six-screen flow in Step 2 of setup), and you may see a shorter version later the first time you use a feature like label PDF export, QR generation for forms, or daily backups, if you didn't grant all permissions upfront.
What to do: click Advanced at the bottom of the warning, then Go to Backend (unsafe), then Continue, then Allow. The "(unsafe)" wording is Google's catch-all for any unverified script. Yours is fine because you're the one installing and running it.
How to avoid it next time: when you do see the full permissions list (the screen titled "See what Backend can access"), tap Select All at the top before continuing. That grants every permission your script will ever need in one go, so you don't get re-prompted later.
If it keeps appearing on a function you've already authorized: something genuinely changed in the script's required permissions, usually because we shipped an update that needs a new capability. Repeat the Advanced, Go to, Continue, Allow flow once and it'll stop.
"Access blocked: Authorization Error, the OAuth client was not fully created yet"
You'll see this if you try to deploy or run a script within a few minutes of copying a fresh template. Google provisions the bound script's OAuth client asynchronously when you make the copy. For the first few minutes after copying, the OAuth client isn't ready and any authorization attempt is blocked.
Fix: wait 5-10 minutes, then try the same step again. The error almost always resolves on its own as Google finishes the behind-the-scenes setup. No action needed on your end other than waiting.
If it persists after 15+ minutes: close the Apps Script editor tab, refresh the spreadsheet, then re-open Apps Script via Extensions → Apps Script. Try Deploy again. If still blocked, trash that copy of the template and make a fresh one. Wait 10 minutes before opening Apps Script in the new copy.
Setup hiccups
Go to fiveanddime.tools/connect/, paste your license key in the first field, and tap Verify install. The site re-shares your library access, probes your backend, and tells you exactly what (if anything) needs attention. Most of the symptoms below can be diagnosed (and often fixed) in one click here.
"Script function not found: somefunctionname" when clicking a menu item
Happens to buyers who set up before a new feature was added to the spreadsheet menu. The menu item itself comes from the library (which auto-updates), but the function it points at has to physically exist in your spreadsheet's bound script — and yours was generated before that feature shipped.
Fix (about 90 seconds):
- Open your spreadsheet → Extensions → Apps Script.
- In the file list on the left, click Shim.gs.
- Scroll to the bottom of the file. Paste the missing function-line(s) the email from support gave you — they look like
function someName(...args) { return FiveAndDimeLib.someName(...args); }— one line per missing function. - Click the floppy-disk Save icon at the top.
- Close the spreadsheet tab, reopen it from your Drive, then try the menu item again.
Email support@fiveanddime.tools with the exact function name from the error (e.g. openCustomOrderRequestPanel) if you don't have it handy and we'll send the lines to paste.
"You do not have access to library xxxxx used by your script, or it has been deleted"
This shows in the Apps Script editor during deploy or when running any function. Behind the scenes, the backend code is a shared library that's granted to your Google account at license time. Two situations break that share:
- The share hasn't reached you yet. New buyers should have access within a minute of buying. If it's been longer, drop a note to support@fiveanddime.tools with your license key and we'll re-share manually.
- You're signed into a different Google account than the one on your license. Very common: you bought with one gmail and started setup signed into another. Self-service fix: go to fiveanddime.tools/connect/email-change/, enter your license key + the new email you want to use. We email your old address with a confirm link; click it, and library access transfers to the new account in one shot. (You'll need access to the current email on file for this to work.)
After we re-share, close the spreadsheet tab, reopen it from your Drive, and try Deploy again. Apps Script caches library references per session, so a reopen is required for the new permission to take effect.
"Update available" banner inside the app
When we ship backend improvements, the library version bumps. Your spreadsheet's bound script is pinned to a specific version, so it doesn't pick up the new code automatically.
In the running app: a small banner at the top of Settings says a new library version is available. Tap the update button; it re-pins the library and reloads. One-tap fix.
In the Apps Script editor: if the in-app updater isn't available yet (very early installs) or didn't work, you can pin manually one time: open the Apps Script editor, click the Libraries icon on the left side (looks like a book), find FiveAndDimeLib, change the version dropdown to the latest number, click Save, then redeploy from Deploy → Manage deployments.
I scanned the setup QR, tapped Apply, and the app is still blank
Recent installs should auto-pull the catalog after the setup card. If yours doesn't, or you missed the catalog-loading status:
- Open the app in a regular browser tab (not the home-screen PWA) at fiveanddime.tools.
- Go to Settings → Sync → tap Pull from Backend Now. Watch for either a green "✓ N products" or a red error message.
- If you get an error: read it. The app explains library-access and authorization failures with specific recovery steps. If it says something generic ("see Settings"), check that the License section shows a valid green status.
- Once the browser tab shows products, your PWA home-screen install will also see them on next launch (they share storage).
The most common cause of a blank app after QR is the install-before-confirm race: you tapped "Add to Home Screen" before tapping Apply setup on the sticky card. The PWA shortcut points at the bare URL with no setup params. Opening the URL fresh in a browser tab and going through Apply again fixes it.
"Business gmail" — Workspace vs. just another personal gmail
fiveanddime works fine with either, with one specific Workspace gotcha to know about.
Are you actually on Workspace? If your email ends in @gmail.com (e.g., myshop@gmail.com), it's a regular personal Google account — no admin restrictions, treat it like any other gmail. If your email ends in a custom domain (@yourbusiness.com) and you sign in through Google, that's a Workspace account.
Workspace-specific issue: Workspace admins can restrict the "Who has access: Anyone" option on Apps Script Web App deployments. If the deploy dialog only offers "Anyone within [your org]", picking that breaks the connection — the fiveanddime frontend isn't in your organization, so it can't reach the backend. Two ways out:
- Use a personal gmail for setup. Email support with your license key and the gmail you want to switch to, we re-share, you redo Step 1 of setup under that account.
- Have your Workspace admin enable external sharing for Apps Script Web Apps. Admin Console → Apps → Google Apps Script → Settings → Allow Web Apps to be accessible from outside the organization.
The other Workspace blocker is a hard "blocked by your administrator" OAuth wall with no Advanced link. That one has no buyer-side workaround; personal gmail is the cleanest path.
Sync & data
Pending sync number won't go down
- Tap the sync chip and confirm the device sees the backend URL set in Settings.
- Force a manual drain: tap Pull from Backend Now in Settings (this also pokes the queue).
- If a specific operation in the queue is failing repeatedly, the queue shows the error. Common culprits: invalid event ID, invalid SKU on a manual item (typo in the SKU field), tax computation mismatch from a recent tax rate change.
- For a stuck queue with a bad row: tap the pending chip → find the offending entry → fix or discard. Discarding loses that operation; only do it if you're sure you can recover the data another way (most often by re-ringing the sale).
Sale rang on Device A doesn't appear on Device B
- Wait ~30 seconds. Device B polls the backend on a 30-second interval; Device A's sale shows up after the next poll.
- If it's been longer than a minute, check that Device A actually synced (its sync chip should be at 0). If A is offline, the sale hasn't reached the backend yet.
- Tap Pull from Backend Now on Device B to force a refresh.
My sheet's QuantityOnHand doesn't match what the app shows mid-event
Expected, not a bug. The app's stock badges (OUT, LOW) are computed live — they account for sales you've already rung in the current event, even before posting. Your Products_Master.QuantityOnHand column on the sheet works on the older two-stage rhythm: it only changes when you tap Post sales to inventory at the end of an event. So mid-event, the sheet's number is "as of the last event you posted," while the app's badge is "as of this minute."
When end-of-event posting runs, the sheet catches up to reality and the two numbers reconcile. Until then, trust the app's badge for in-the-moment decisions and the sheet for historical reporting.
If you want a live look at "what's effectively on hand right now" without doing the math yourself, the items-grid badges (OUT in red, LOW in orange) carry that signal — that's why we built them to compute live rather than read straight off the sheet.
Inventory looks wrong after an event
- Did you tap Post sales to inventory on the Events tab for that event? Sales accumulate as line items but don't decrement QuantityOnHand until posting runs.
- Was the event marked as IsTestEvent=TRUE? Test events refuse posting; switch the event's flag to FALSE if it should have posted, then retry.
- Did you wait for the sync queue to drain before posting? If sales were still queued, they wouldn't have been included. Pull from Backend, confirm the queue is at 0, then re-tap post (safe to re-run; won't double-decrement).
- Did any sales get voided? Voided sales drop out of posting. Check the Events tab for VOIDED badges on rows you expected to count.
- Last resort: cycle count the affected SKUs. See the Tracking inventory tutorial.
End-of-Event card says "X unposted line items across 0 SKUs"
Means the event was rung as all manual items (no catalog SKU). Manual items have nothing in your catalog to decrement, so the inventory math is a no-op — but you still tap Post sales to inventory to mark them as accounted-for and clear the reminder card. Then Pull from Backend Now to refresh the device. Card disappears.
Mixed events (some catalog, some manual) show the same way with a smaller "0" — e.g., "5 line items across 2 SKUs" means 2 catalog items will decrement and 3 manual items will just get marked posted.
I rang the same sales twice by accident
Happens when you're not sure whether the first ring saved and re-enter from scratch (especially when backfilling from a paper list). The system doesn't catch it — each tap on Complete sale creates a fresh SaleID. To clean up:
- Open Events tab, find the duplicate sale rows. Look for matching totals + close timestamps as the giveaway.
- Tap Void on each duplicate. Don't try to delete the rows from the Sales sheet — voiding preserves the audit trail and excludes them from reports and end-of-event posting.
- Tap Post sales to inventory if it's prompting (the voided sales drop out automatically; posting is idempotent and safe to re-tap).
- Pull from Backend Now to refresh totals on this device.
Your Sales totals will now reflect the real number of transactions. If the items had SKUs and you already posted before noticing, voiding doesn't reverse the inventory decrement — do an Inventory adjustment (Settings → Inventory adjustment) to add back the over-decremented quantity, reason "count_discrepancy."
Catalog & products
Added a product but it's not in the app
- Tap Pull from Backend Now in Settings on the device. Catalog changes don't auto-refresh.
- Check that the product's
Activecheckbox is checked (unchecked hides from booth). - Check that
BringToShowis TRUE (FALSE hides from the items grid even when active). - Check that the product's
Categorymatches a Code in the Categories sheet.
Category tab is missing or shows the wrong name
- The Categories sheet drives the tabs. Check that the Category Code on your products matches an existing Code row in Categories.
- If DisplayName is blank in Categories, the tab shows the raw Code. Fill in DisplayName.
- Pull from Backend on the device after editing Categories.
Bundle isn't auto-applying
- Check the Bundles sheet:
Activecolumn must be TRUE for the bundle. - Check eligibility: do the cart items match the bundle's
EligibleCategory,EligibleParent, orEligibleSkus? Items must also NOT be inExcludeSkus. - Check
MinQty: the cart needs at least that many eligible items. - Pull from Backend after editing Bundles. The frontend caches the bundle definitions until you pull.
Parent product won't open the variant chooser
- Verify variant rows in
Products_MasterhaveParentSKUmatching the parent's SKU exactly. Case-sensitive. - At least one variant must have BringToShow=TRUE (or appear in the chooser even with BringToShow=FALSE; the chooser shows all linked variants).
- Pull from Backend.
Sale flow
Complete sale button is disabled
- Cart is empty. Add at least one item.
- No payment method selected. Tap one of Cash/Card/Venmo (or whatever you've configured in
PAYMENT_METHODS). - No active event. Tap the event chip and pick one.
Cart line is wrong after a price override
- Tap the line's price field and retype. The cart updates immediately.
- If you want to reset to the catalog price, type the original value or remove the line and re-add it.
Tax looks wrong on a sale
- Check the event's TaxRate column. The cart's tax is back-computed from the event's rate (or added on top in TAX_MODE=added).
- Tax-exempt checked? Tax = 0 by design.
- Different tax mode than expected? Check Settings → Tax in the app (canonical key
TAX_MODE). Included means sticker prices are tax-inclusive; added means tax is added on top at checkout.
Scanner
Camera permission denied
- iPhone Safari: Settings (iOS) → Safari → Camera → Allow.
- Android Chrome: tap the lock icon in the address bar → Permissions → Camera → Allow.
- After granting, reload the app.
Scanner sees the barcode but nothing happens
- The SKU on the label doesn't match anything in
Products_Master. Verify the SKU exists in the sheet, then pull from backend. - Casing matters.
BOO00andboo00aren't the same SKU. - Reprint the label if the printed SKU is garbled.
Scanner doesn't recognize the barcode at all
- Lighting; try moving to better light.
- Wrinkled or torn label; reprint.
- Try Tap-to-scan mode if Live mode keeps missing the read.
- If your browser doesn't support barcode scanning at all (rare on phones, more common on Windows Chrome), the manual SKU search in the Sale view works on every device.
Product photos
Photos work on my laptop but not on my phone (grey box appears then disappears)
The "grey box flashes and disappears" pattern means the image URL is reaching your phone correctly — the browser tries to render it, the fetch fails, the button silently falls back to text-only. The image data is the same on both devices, so the difference is in how each device accesses it.
By far the most common cause: the Drive folder (or individual photo file) isn't publicly shared. Your laptop browser is signed into the Google account that owns the photos, so Drive serves the image based on your authentication cookie. Your phone browser isn't signed into the same account (or isn't signed into Google at all), so the same URL returns a "sign in to view" page instead of the image, and the <img> tag errors out.
Fix (one folder share covers everything):
- Open Drive on any browser.
- Find the folder where your product photos live.
- Right-click → Share.
- Under "General access," change Restricted to Anyone with the link.
- Set the role to Viewer. Click Done.
Photos become visible to anyone with the URL, but the URLs are long random strings — effectively private in practice. Your spreadsheet, your sales data, and the rest of your Drive aren't affected. After sharing, close and reopen the fiveanddime app on your phone so it stops using cached "this URL doesn't work" entries, then the photos appear.
If you'd rather not share a whole folder: share photos individually with the same setting. For more than a handful, the folder approach is far less work.
Photos work on no device — including my laptop
- Did you pull from backend after adding the photos? In the app: Settings → Pull from Backend Now.
- Open Settings — is there an "Update available" or "Fix product photo URLs" banner at the top? If yes, tap through it. We auto-detect Drive share-style URLs (the ones that go to a viewer page instead of the image bytes) and offer a one-tap migration that converts them to the right format.
- Pasted a per-product URL by hand? Drive share links (the ones with
/file/d/.../viewin them) don't render as images. After updating to library v8, new pastes auto-convert on save. For URLs pasted before v8, run the "Fix product photo URLs" migration above. - Check
Products_Master.ImageUrlin your sheet. If it's empty for a product, that product won't have a photo regardless. If it's filled, paste the value into a new browser tab and see if the image loads — if not, the URL itself is broken.
Receipts
Receipt QR shows but customer's phone can't open the link
- Customer needs working internet on their phone. The receipt page is served from your app's domain at the
/r/path; if they're offline, the page won't load. - Customer's camera app may not support QR scanning. Most modern phones do, but if not, they can open the link manually.
- The QR encodes the receipt data directly in the URL, so receipts are self-contained. No backend required to render.
License
"Cached" warning banner
The licensing service couldn't be reached to revalidate your license, so the app is operating from the last-known-good cached state. License is still valid; you can keep selling. The banner clears the next time the device reaches the licensing service successfully.
- Most often: temporary network blip or the licensing service is briefly down.
- Caches are good for up to 7 days. If you're consistently offline longer than that, the app will eventually fall back to a more restrictive mode.
"Blocked" or "Invalid"
- "Blocked" usually means a typo or stray space in the license key. Open Settings → License → re-paste carefully, save, validate.
- "Invalid" means the licensing service rejected the key (wrong key, account issue, etc.). Email support@fiveanddime.tools with your license key and what happened.
Auto-email (custom orders)
Auto-email didn't fire when I marked an order Ready
- Is the auto-email checkbox enabled? Open Settings → Custom orders in the app and confirm Auto-email the customer when I mark their custom order Ready is checked, then tap Save. (Canonical key:
NOTIFY_EMAIL_ON_READY.) Anything other than checked/TRUEkeeps the manual workflow. - Does the order have a CustomerEmail value? Auto-email requires it.
- First time you mark Ready after enabling, Google prompts for email permission. If you missed the prompt, run the manual notify once from the Orders panel to trigger it again.
- If none of the above explains it, email support@fiveanddime.tools with the order's customer name and approximate time you marked it Ready. We can check the backend logs to see what happened.
Backups
Daily auto-backup doesn't seem to run
- Did you tap Set up daily auto-backup in the fiveanddime → Backups menu? It needs a one-time setup.
- Check the fiveanddime-Backups folder in your Drive. If there's a file dated within the last day or two, it's working.
- Triggers can be disabled by Google if the script hasn't been authorized for the right scopes. Run Backup now from the same menu to re-confirm permissions.
Saving and restoring pending sales (JSON export)
When you ring a sale offline, it sits in this device's local storage until you reconnect and the queue drains. Most of the time you just wait for the drain. But in rare cases (browser data accidentally cleared, you have to switch devices unexpectedly, you suspect the queue is corrupted) you want a way to grab those pending sales as a file and restore them later.
The Settings tab has a Backup & recovery section with two buttons for exactly this:
Save unsynced sales (JSON)
Tap the button. The app downloads a file named something like fiveanddime-pending-2026-05-10-1430.json. That file contains every queued operation on this device that hasn't synced yet (sales, voids, post-event requests, inventory adjustments, product edits).
Save the file somewhere safe: email it to yourself, drop it in Drive, AirDrop to another device, whatever you trust. The file is plain JSON; it doesn't contain credentials, just the operation data.
Restore from saved JSON
Tap the button, pick the JSON file you previously saved (or one you've moved to this device from another). The app re-adds those operations to the queue. They sync to the backend on the next drain (or you can tap Pull from Backend Now to nudge it).
Restoring is safe to re-run on the backend: sales have unique SaleIDs, so re-submitting one that already made it through won't double-post. Safe to restore a backup even if you're not sure whether the originals synced.
Discard all pending entries
Last resort. Below the save/restore buttons, the Discard all pending entries button wipes the local queue. Use this only when a specific queued entry keeps failing because its data is no longer valid (references a deleted SKU, deleted event, etc.) and you've already saved the JSON copy of anything you want to keep. Discarded entries can't be recovered after.
99% of vendors never need any of this. Sales queue and drain in normal use. Use the save/restore flow if you're about to clear your browser data, switch to a new phone, or troubleshoot a stuck queue and want a safety copy first. Use Discard only when you've identified a specific bad entry and have backed up the rest.
Stuck in a weird state? Two nuclear options
In Settings, scroll to Pull from Backend Now and tap. This re-downloads catalog, events, categories, bundles, and settings from your spreadsheet. Fixes most "stale UI" issues. Won't lose any queued sales (they stay queued).
If something is genuinely broken on the device (rare): uninstall the PWA from your home screen, clear the site data in your browser's settings (look for your fiveanddime install's domain in the site list), reinstall fresh from the URL. Warning: if you have pending un-synced sales in the queue, this wipes them. Either drain the queue to 0 first (Pull from Backend Now, wait), or use the JSON export below to save them first.
When to email support
If nothing here helps: support@fiveanddime.tools. Useful info to include:
- What you were doing when it broke.
- What you expected to happen vs. what actually happened.
- Whether you've tried Pull from Backend.
- The diagnostic dump. Open Settings → Diagnostics, tap Refresh diagnostics, tap Copy to clipboard, paste into your email. This captures device info, sync state, queue counts, current event, license state, and everything support needs to triage without playing 20 questions. Nothing in it is secret (no license-key value, no API-secret value, no sales data), just configuration and counts.