Prevent accidental modification of sacred spreadsheet formulas in Google Sheets Portfolio Tracker. Blocks edits to GOOGLEFINANCE formulas, calculated columns, and total rows. Allows only IFERROR wrappers, fixing broken references, and expanding ranges. Triggers on update formula, modify column, fix errors, or any attempt to edit formula-based cells.
GUARDRAIL SKILL - Prevents accidental modification or deletion of critical formulas that maintain spreadsheet integrity. Ensures financial data accuracy by protecting auto-calculated columns.
This skill automatically blocks when detecting:
This is a BLOCKING skill - You MUST use this skill before proceeding with any formula-related edits.
Column C: Last Price
=GOOGLEFINANCE(A2, "price")
Columns D-E: $ Change, % Change
=C2 - G2 ($ Change)
=D2 / G2 (% Change)
Columns H-M: Gains/Losses
=L2 - M2 (Total G/L $)
=K2 / M2 (Total G/L %)
=B2 * C2 (Current Value)
=B2 * G2 (Cost Basis Total)
Columns N-S: Advanced Metrics
Column F: Total Dividend $
=D2 * E2 (Shares × Dividend Per Share)
Total Row Formula
=SUM(F2:F50) (TOTAL EXPECTED DIVIDENDS)
Coverage Ratio
=IFERROR(B10 / B11, 0) (Dividends ÷ Interest Cost)
Purpose: Prevent error display without changing logic
Example:
Before: =GOOGLEFINANCE(A2, "price")
After: =IFERROR(GOOGLEFINANCE(A2, "price"), "N/A")
Before: =B10 / B11
After: =IFERROR(B10 / B11, 0)
When to use:
Purpose: Correct renamed or moved sheet names
Example:
Before: =Sheet1!A1
After: ='DataHub'!A1
Before: ='Dividend Tracker OLD'!B10
After: ='Dividend Tracker'!B10
When to use:
Purpose: Include new data rows without changing logic
Example:
Before: =SUM(F2:F50)
After: =SUM(F2:F100)
Before: =AVERAGE(B2:B30)
After: =AVERAGE(B2:B50)
When to use:
Purpose: Correct obvious mistakes in formula construction
Example:
Before: =B100 * C100 (B100 doesn't exist)
After: =B10 * C10
Before: =A2 + A2 (duplicate cell reference)
After: =A2 + B2 (correct cells)
When to use:
Example of what NOT to do:
❌ =SUM(F2:F50) → =AVERAGE(F2:F50) (changes meaning)
❌ =B2 * C2 → =B2 + C2 (changes calculation)
❌ =GOOGLEFINANCE(A2, "price") → =GOOGLEFINANCE(A2, "volume")
Why: Changes the meaning of calculated data, breaks dashboard integrity
Example of what NOT to do:
❌ =GOOGLEFINANCE("TSLA", "price") → 445.47 (hardcoded)
❌ =B2 * C2 → 32964.78 (static value)
❌ =SUM(F2:F50) → 2847.32 (loses dynamic calculation)
Why: Data becomes stale, no longer updates automatically
Example of what NOT to do:
❌ Deleting Column C (Last Price formulas) to "clean up"
❌ Removing total row formulas to "simplify"
❌ Clearing formula cells to "start fresh"
Why: Destroys data pipeline, breaks all dependent calculations
Example of what NOT to do:
❌ =GOOGLEFINANCE(A2, "price") → =GOOGLEFINANCE(A2, "closeyest")
❌ =GOOGLEFINANCE("TSLA", "price") → =GOOGLEFINANCE("NASDAQ:TSLA", "price")
Why: May break price lookups, change data source unexpectedly
Scan spreadsheet for:
GOOGLEFINANCE failures (Column C):
Cause: Stock delisted, ticker invalid, or Google Finance API issue
Solution: Wrap with IFERROR()
=IFERROR(GOOGLEFINANCE(A2, "price"), "DELISTED")
VLOOKUP failures (if used):
Cause: Lookup value doesn't exist in source data
Solution: Check source data exists, expand range, or add IFERROR()
=IFERROR(VLOOKUP(A2, Data!A:B, 2, FALSE), "NOT FOUND")
Margin coverage ratio (when margin = $0):
Before: =B10 / B11
After: =IFERROR(B10 / B11, 0)
Percentage calculations (when denominator = 0):
Before: =K2 / M2
After: =IFERROR(K2 / M2, 0)
Deleted rows/columns:
Cause: Formula references Sheet1!A10 but row 10 was deleted
Solution: If temporary, wrap with IFERROR(). If permanent, reconstruct formula.
Temporary: =IFERROR(Sheet1!A10, 0)
Permanent: Identify correct new reference and update
Before applying broadly:
After repair:
Log all changes:
✅ Fixed #DIV/0! in Margin Dashboard C10 by adding IFERROR()
Formula change: =B10/B11 → =IFERROR(B10/B11, 0)
Reason: Margin balance was $0 causing division by zero
Date: 2025-11-11
Ask yourself:
spreadsheet-architecture.md? (Required)If ANY stop condition triggered: Use this skill, review rules, proceed with caution
If formula modification breaks the spreadsheet:
User request: "The price for TSLA isn't updating, let me fix the formula"
Agent response:
🛑 BLOCKED by formula-protection skill
You're attempting to modify Column C (Last Price) which contains GOOGLEFINANCE formulas.
These are sacred formulas and must NEVER be modified.
If TSLA price isn't updating, the issue is likely:
1. Google Finance API delay (wait 5-10 minutes)
2. Market is closed (prices only update during trading hours)
3. Ticker symbol incorrect (verify "TSLA" is correct)
❌ Do NOT modify =GOOGLEFINANCE(A2, "price")
✅ If truly broken, wrap with: =IFERROR(GOOGLEFINANCE(A2, "price"), "N/A")
User request: "Column C shows #N/A for delisted stock, can you fix?"
Agent response:
✅ Using formula-protection skill
I'll safely wrap the GOOGLEFINANCE formula with IFERROR() to handle the delisted stock.
Before: =GOOGLEFINANCE(A45, "price")
After: =IFERROR(GOOGLEFINANCE(A45, "price"), "DELISTED")
This preserves the formula logic while displaying "DELISTED" instead of #N/A.
The formula will still work if the stock relists in the future.
✅ Safe operation - formula logic unchanged
User request: "Total dividends formula only goes to row 50, but I have 55 funds now"
Agent response:
✅ Using formula-protection skill
I'll safely expand the SUM range to include all 55 funds.
Before: =SUM(F2:F50)
After: =SUM(F2:F100)
This expands the range to accommodate current data (55 funds) plus room for growth.
Formula logic unchanged - still summing Total Dividend $ column.
✅ Safe operation - range expanded, logic preserved
Spreadsheet ID: Read from fin-guru/data/user-profile.yaml → google_sheets.portfolio_tracker.spreadsheet_id
Use the mcp__gdrive__sheets tool:
Read-only operations (to detect formula errors):
// STEP 1: Read Spreadsheet ID from user profile
// Load fin-guru/data/user-profile.yaml
// Extract: google_sheets.portfolio_tracker.spreadsheet_id
// STEP 2: Scan for errors
mcp__gdrive__sheets(
operation: "spreadsheets.values.get",
params: {
spreadsheetId: SPREADSHEET_ID, // from user-profile.yaml
range: "DataHub!A1:Z100"
}
)
// Check for #N/A, #DIV/0!, #REF! in returned values
Write operations (only for safe repairs):
// Add IFERROR wrapper to fix formula errors
mcp__gdrive__sheets(
operation: "spreadsheets.values.update",
params: {
spreadsheetId: SPREADSHEET_ID, // from user-profile.yaml
range: "DataHub!C2:C2",
valueInputOption: "USER_ENTERED",
requestBody: {
values: [["=IFERROR(GOOGLEFINANCE(A2, \"price\"), \"N/A\")"]]
}
}
)
Builder (Write-enabled with formula-protection):
All Other Agents (Strictly Read-only):
For complete details, see:
fin-guru/data/spreadsheet-architecture.md (lines 380-440)fin-guru/data/spreadsheet-quick-ref.mdfin-guru/data/spreadsheet-architecture.md (lines 91-136)Remember:
When in doubt: READ-ONLY and ASK USER for guidance.
Skill Type: Guardrail (safety mechanism) Enforcement: BLOCK (prevents formula modifications) Priority: Critical Line Count: < 500 (following 500-line rule) ✅