Hi Community,
I’m Felix, and some of you might know me from the first workflow I’ve built and shared. My first project was an invoice data extraction automation that used Telegram as an interface. I could upload photos or PDFs, process them, and have the extracted data automatically added to a Google Sheet. That way, I could easily share an overview with my tax lawyer. You can find the workflow here: Automated expense tracking with Telegram, easybits & Google Sheets | n8n workflow template
Here’s a quick look at my tech stack:
-
n8n – workflow automation
-
easybits – document extraction API
-
Telegram Bot API
-
Google Sheets API
While building this workflow, I ran into a lot of small (and not-so-small) issues. I figured it might be useful to share them with the community, along with how I solved them. Your setup might be different, but hopefully, you’ll pick up some ideas.
Lesson 1: Google Sheets Formulas Keep Breaking?
Use OVERWRITE instead of INSERT_ROWS.
INSERT_ROWS shifts your data down and breaks your formulas. OVERWRITE appends without shifting, keeping everything intact.
Lesson 2: Numbers Stored as Text
My SUM formula kept returning zero. The numbers looked fine but were actually stored as text.
Fix: UsevalueInputOption=USER_ENTEREDinstead ofRAW.
Lesson 3: “No grid with id: 0” Error
This one drove me crazy. When working with existing sheets, the sheetId isn’t always 0.
Fix: Add a “Get Sheet Info” node to fetch the actual sheetId before formatting.
Lesson 4: Handle Both Photos AND PDFs
My first version only accepted photos. I forgot people also send invoices as PDFs.
{{ $json.body.message.photo || $json.body.message.document ? 'yes' : 'no' }}
Lesson 5: Dynamic Sheet Names
I had hardcoded “December_2025” in my URL and then wondered why September receipts went to the wrong sheet.
Fix: Use expressions to generate the sheet name dynamically from your data.
Lesson 6: Partial Reimbursement Rates
My employer covers 80% of phone bills. I added this into the workflow:
let eurRate = 1;
if (category === 'Mobile Phone') {
eurRate = 0.8;
}
const eurAmount = totalAmount * eurRate;
Now the sheet shows the actual claimable amount.
Lesson 7: Handle Unknown Categories Gracefully
Not every receipt fits neatly into a category. Instead of defaulting to “Other,” the bot now asks:
“I could not determine the category. Please resend with a caption: Office Supplies, Marketing, Equipment…”
The user sends the photo again with a caption. Problem solved.
Lesson 8: Flexible Descriptions
Users want control. I built a simple caption format:
-
Marketing → Category: Marketing, Details: Business Expense -
Marketing - Client gift → Category: Marketing, Details: Client gift
Simple separator, maximum flexibility.
Lesson 9: Apply Formatting AFTER Data Insertion
I pre-formatted cells with bold text. Then I added data, and formatting disappeared.
Lesson learned: Data insertion overwrites formatting. Always apply formatting after inserting data.
That’s it! Hopefully, some of these tips help you avoid the mistakes I made.
If you’ve run into similar problems or have questions, feel free to leave a comment – I’d love to hear your experiences!

