Skill Tracer
Skills › Knowledge Work Plugins › canva-creator › gotchas.md

gotchas.md

380 lines · small-business/skills/canva-creator/reference/gotchas.md at 2574e29

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Gotchas
2
3Common failure modes for the canva-creator skill.
4
5---
6

Gotchas

Common failure modes for the canva-creator skill.


Raw lines 1 to 6
7## Gotcha: Generating ANY Canva design for an email row
8
9**Why it matters:** Canva is out of scope for the email path entirely.
10Canva email-template autofill produces placeholder graphics (stock
11landscapes, blank rectangles) in service-grid tiles, and variation
12thumbnails fail to render in chat. Emails are text-only
13from this skill, period. Generating a Canva email design — even one —
14breaks that rule.

Gotcha: Generating ANY Canva design for an email row

Why it matters: Canva is out of scope for the email path entirely. Canva email-template autofill produces placeholder graphics (stock landscapes, blank rectangles) in service-grid tiles, and variation thumbnails fail to render in chat. Emails are text-only from this skill, period. Generating a Canva email design — even one — breaks that rule.

Raw lines 7 to 15
16### ✗ Bad
18```
19Calendar has 6 social rows + 2 email rows.
20→ Stage 2 generates 6 social designs + 2 email designs.
21→ Email designs ship with placeholder service tiles.
22```
24Or any variation: "I'll generate the email template just to give you a
25visual reference," "I found an email template that might work, want to
26preview it?", "Here's a Canva design for the Jun 5 email…" — all
27forbidden.

✗ Bad

Calendar has 6 social rows + 2 email rows.
→ Stage 2 generates 6 social designs + 2 email designs.
→ Email designs ship with placeholder service tiles.

Or any variation: "I'll generate the email template just to give you a visual reference," "I found an email template that might work, want to preview it?", "Here's a Canva design for the Jun 5 email…" — all forbidden.

Raw lines 16 to 28
29### ✓ Good
31```
32Stage 1: Calendar built with Path column.
33 - 6 rows tagged Canva (social)
34 - 2 rows tagged Text-only (no Canva)
35Stage 2: Generates exactly 6 Canva designs. Email rows are not passed
36 to any Canva endpoint.
37Stage 3: Drafts 6 social captions + 2 full emails (subject + preheader +
38 body) as plain text.
39Stage 4: Stages 6 social posts in HubSpot. Surfaces 2 emails inline for
40 owner to copy into their email tool.
41```
43If the owner explicitly asks for a Canva email design ("can you make me
44a Canva version of the Jun 5 email?"), redirect: "This skill keeps emails
45as text-only because the Canva email path produces placeholder graphics.
46If you want a Canva-designed email, build it directly in Canva and I can
47help you write the copy here."
49---

✓ Good

Stage 1: Calendar built with Path column.
  - 6 rows tagged Canva (social)
  - 2 rows tagged Text-only (no Canva)
Stage 2: Generates exactly 6 Canva designs. Email rows are not passed
         to any Canva endpoint.
Stage 3: Drafts 6 social captions + 2 full emails (subject + preheader +
         body) as plain text.
Stage 4: Stages 6 social posts in HubSpot. Surfaces 2 emails inline for
         owner to copy into their email tool.

If the owner explicitly asks for a Canva email design ("can you make me a Canva version of the Jun 5 email?"), redirect: "This skill keeps emails as text-only because the Canva email path produces placeholder graphics. If you want a Canva-designed email, build it directly in Canva and I can help you write the copy here."


Raw lines 29 to 50
51## Gotcha: Generating without a budget plan
53**Why it matters:** Canva caps API usage at 100 requests/minute per token,
54and each design costs ~5 calls (autofill + export + polling). A 10-row
55campaign with 4 candidates per row generates 40 designs and ~200 API
56calls — and the math gets worse with parallelism. Without a pre-flight
57budget, the owner hits quota mid-campaign with no clear recovery path
58and four already-generated posts sitting unused.

Gotcha: Generating without a budget plan

Why it matters: Canva caps API usage at 100 requests/minute per token, and each design costs ~5 calls (autofill + export + polling). A 10-row campaign with 4 candidates per row generates 40 designs and ~200 API calls — and the math gets worse with parallelism. Without a pre-flight budget, the owner hits quota mid-campaign with no clear recovery path and four already-generated posts sitting unused.

Raw lines 51 to 59
60### ✗ Bad
62```
63Calendar approved → immediately fire 4 candidates × 8 rows in parallel
64→ ~160 API calls in 90 seconds → RATE_LIMIT_EXCEEDED on post 5 → loop
65on retry → owner blocked.
66```

✗ Bad

Calendar approved → immediately fire 4 candidates × 8 rows in parallel
→ ~160 API calls in 90 seconds → RATE_LIMIT_EXCEEDED on post 5 → loop
on retry → owner blocked.
Raw lines 60 to 67
68### ✓ Good
70```
71Pre-flight: "8 Canva rows × 3 candidates = 24 designs, ~120 API calls.
72Proceed at default 3 candidates per row?"
74Stage 3: row 1's 3 candidates fire in parallel → 30s pause → row 2 →
7530s pause → row 3 → … finishes at ~12 designs/minute, well under the
76quota.
78If quota does hit anyway: stop, surface progress, ask the owner
79whether to drop to single candidates, pause an hour, or move to
80captions with what's done.
81```
83---

✓ Good

Pre-flight: "8 Canva rows × 3 candidates = 24 designs, ~120 API calls.
Proceed at default 3 candidates per row?"

Stage 3: row 1's 3 candidates fire in parallel → 30s pause → row 2 →
30s pause → row 3 → … finishes at ~12 designs/minute, well under the
quota.

If quota does hit anyway: stop, surface progress, ask the owner
whether to drop to single candidates, pause an hour, or move to
captions with what's done.

Raw lines 68 to 84
85## Gotcha: Skipping Checkpoint 1 (calendar approval) before generating assets
87**Why it matters:** Generating 10+ Canva designs takes API calls, time, and
88user attention. If the calendar has the wrong dates, wrong channels, or the
89owner changes their mind about a theme, all that work is discarded. The
90calendar checkpoint is the cheapest place to catch misalignment.

Gotcha: Skipping Checkpoint 1 (calendar approval) before generating assets

Why it matters: Generating 10+ Canva designs takes API calls, time, and user attention. If the calendar has the wrong dates, wrong channels, or the owner changes their mind about a theme, all that work is discarded. The calendar checkpoint is the cheapest place to catch misalignment.

Raw lines 85 to 91
92### ✗ Bad
94Receive the brief → immediately start calling `POST /autofills` for all 12
95posts → present designs before the owner has agreed on the schedule.
97Owner: "Oh wait, I didn't want any posts the week of the 15th, I'm traveling."

✗ Bad

Receive the brief → immediately start calling POST /autofills for all 12 posts → present designs before the owner has agreed on the schedule.

Owner: "Oh wait, I didn't want any posts the week of the 15th, I'm traveling."

Raw lines 92 to 98
99### ✓ Good
101Present the calendar table first. Wait for explicit "looks good" before opening
102a single Canva API call.
104---

✓ Good

Present the calendar table first. Wait for explicit "looks good" before opening a single Canva API call.


Raw lines 99 to 105
106## Gotcha: Template has more image slots than the brief provides photos for
108**Why it matters:** Multi-image social templates (Instagram carousels,
109product grids) can have 3+ image slots. When the brief gives you 1 photo
110and the template demands 3, the unfilled slots silently render Canva's
111stock landscape graphic — generic clouds and green hills where product
112photos should be. The design looks "complete" until the owner opens it.
114(Note: email rows skip Canva entirely in this skill — see SKILL.md Stage 3.
115This gotcha applies only to social templates with multiple image slots.)

Gotcha: Template has more image slots than the brief provides photos for

Why it matters: Multi-image social templates (Instagram carousels, product grids) can have 3+ image slots. When the brief gives you 1 photo and the template demands 3, the unfilled slots silently render Canva's stock landscape graphic — generic clouds and green hills where product photos should be. The design looks "complete" until the owner opens it.

(Note: email rows skip Canva entirely in this skill — see SKILL.md Stage 3. This gotcha applies only to social templates with multiple image slots.)

Raw lines 106 to 116
117### ✗ Bad
119Build manifest with one row per design ("Carousel — needs Hero_Image").
120Upload the one photo. Generate. Carousel ships with slide 1 populated
121and slides 2-3 both showing identical generic landscapes.

✗ Bad

Build manifest with one row per design ("Carousel — needs Hero_Image"). Upload the one photo. Generate. Carousel ships with slide 1 populated and slides 2-3 both showing identical generic landscapes.

Raw lines 117 to 122
123### ✓ Good
125Build manifest slot-by-slot. Surface the gap explicitly:
127```
128The "3-product carousel" template has 3 image slots. The brief gave me
1291 photo. How should I fill the other 2?
1311. Reuse the same photo across all 3 slots
1322. I'll send you 2 more photos
1333. Pick a single-image template
134```
136Wait for the owner's choice before generating. Don't let placeholder
137graphics ship.
139---

✓ Good

Build manifest slot-by-slot. Surface the gap explicitly:

The "3-product carousel" template has 3 image slots. The brief gave me
1 photo. How should I fill the other 2?

1. Reuse the same photo across all 3 slots
2. I'll send you 2 more photos
3. Pick a single-image template

Wait for the owner's choice before generating. Don't let placeholder graphics ship.


Raw lines 123 to 140
141## Gotcha: Trusting `status: success` without exporting and visually verifying
143**Why it matters:** A successful autofill job means Canva accepted the
144request and produced a design — not that the design contains the right
145images. If an `asset_id` was empty, stale, or wrong-typed, the job still
146returns `status: success` and the design renders with default placeholder
147graphics. The only way to know is to look at the rendered output.

Gotcha: Trusting status: success without exporting and visually verifying

Why it matters: A successful autofill job means Canva accepted the request and produced a design — not that the design contains the right images. If an asset_id was empty, stale, or wrong-typed, the job still returns status: success and the design renders with default placeholder graphics. The only way to know is to look at the rendered output.

Raw lines 141 to 148
149### ✗ Bad
151```
152Job status: success ✓
153result.design.id: present ✓
154→ Present to owner
155```
157Result: owner opens the carousel and sees stock landscape graphics in 3 of
1584 designs.

✗ Bad

Job status: success ✓
result.design.id: present ✓
→ Present to owner

Result: owner opens the carousel and sees stock landscape graphics in 3 of 4 designs.

Raw lines 149 to 159
160### ✓ Good
162After the job succeeds, export each design to a permanent PNG via
163`POST /exports` (or `export-design` MCP). Look at each PNG and confirm it
164contains real assets — not Canva's default landscape, not gray rectangles,
165not lorem-ipsum text. Only present to the owner after visual verification
166passes.
168---

✓ Good

After the job succeeds, export each design to a permanent PNG via POST /exports (or export-design MCP). Look at each PNG and confirm it contains real assets — not Canva's default landscape, not gray rectangles, not lorem-ipsum text. Only present to the owner after visual verification passes.


Raw lines 160 to 169
Uses an outside tool MCP :163
170## Gotcha: One design in a batch fails to render
172**Why it matters:** When 1 of 4 designs in a batch fails (job error, expired
173preview URL, placeholder rendered) and you present the partial carousel
174anyway, the owner sees three real designs and one "Show Image" gray
175rectangle. They lose trust in the rest of the carousel even though it's
176fine.

Gotcha: One design in a batch fails to render

Why it matters: When 1 of 4 designs in a batch fails (job error, expired preview URL, placeholder rendered) and you present the partial carousel anyway, the owner sees three real designs and one "Show Image" gray rectangle. They lose trust in the rest of the carousel even though it's fine.

Raw lines 170 to 177
178### ✗ Bad
180```
181Week 1 designs are ready:
182[Option A — real preview]
183[Option B — real preview]
184[Option C — real preview]
185[Option D — Show Image placeholder]
186Which one should I use?
187```

✗ Bad

Week 1 designs are ready:
[Option A — real preview]
[Option B — real preview]
[Option C — real preview]
[Option D — Show Image placeholder]
Which one should I use?
Raw lines 178 to 188
189### ✓ Good
191When you detect the broken design at Step 6 verification, regenerate just
192that one design with the correct asset_id. Re-export, re-verify. Only
193present once all four designs in the batch have permanent, verified
194previews. If the second attempt also fails, ask the owner whether to skip,
195swap template, or try a different photo.
197---

✓ Good

When you detect the broken design at Step 6 verification, regenerate just that one design with the correct asset_id. Re-export, re-verify. Only present once all four designs in the batch have permanent, verified previews. If the second attempt also fails, ask the owner whether to skip, swap template, or try a different photo.


Raw lines 189 to 198
199## Gotcha: Generating assets without confirming all autofill fields have values
201**Why it matters:** Canva autofill silently renders empty placeholders when a
202field value is missing or the referenced `asset_id` doesn't exist. The result
203is a professional-looking template with blank white rectangles where the
204product photo and headline should be.

Gotcha: Generating assets without confirming all autofill fields have values

Why it matters: Canva autofill silently renders empty placeholders when a field value is missing or the referenced asset_id doesn't exist. The result is a professional-looking template with blank white rectangles where the product photo and headline should be.

Raw lines 199 to 205
206### ✗ Bad
208Build calendar → immediately fire all `POST /autofills` in parallel → half
209the designs come back with empty image placeholders because product photos
210weren't uploaded first.

✗ Bad

Build calendar → immediately fire all POST /autofills in parallel → half the designs come back with empty image placeholders because product photos weren't uploaded first.

Raw lines 206 to 211
212### ✓ Good
214Build calendar → inventory every autofill field slot-by-slot → upload missing
215product images → confirm all field values with owner → then generate designs
216in parallel, with every field pre-populated.
218---

✓ Good

Build calendar → inventory every autofill field slot-by-slot → upload missing product images → confirm all field values with owner → then generate designs in parallel, with every field pre-populated.


Raw lines 212 to 219
220## Gotcha: Passing invalid values to image autofill fields
222**Why it matters:** When an autofill image field receives an empty string, a
223file path, a URL, or a stale/invalid `asset_id`, Canva does not error — it
224silently renders the template's default placeholder graphic (e.g., a generic
225landscape with clouds and hills). The design looks "finished" but the hero
226image is stock art, not the owner's product photo.

Gotcha: Passing invalid values to image autofill fields

Why it matters: When an autofill image field receives an empty string, a file path, a URL, or a stale/invalid asset_id, Canva does not error — it silently renders the template's default placeholder graphic (e.g., a generic landscape with clouds and hills). The design looks "finished" but the hero image is stock art, not the owner's product photo.

Raw lines 220 to 227
228### ✗ Bad
230Upload product photo → don't wait for the upload job to complete → pass the
231`job_id` (not the `asset.id`) into the autofill data → design renders with
232a placeholder landscape instead of the product photo.

✗ Bad

Upload product photo → don't wait for the upload job to complete → pass the job_id (not the asset.id) into the autofill data → design renders with a placeholder landscape instead of the product photo.

Raw lines 228 to 233
234### ✓ Good
236Upload product photo via `POST /v1/asset-uploads` → poll
237`GET /v1/asset-uploads/{job_id}` until `status == "success"` → extract
238`asset.id` from the response → pass that exact ID into the autofill image
239field. Verify every image field has a confirmed `asset.id` before calling
240`POST /autofills`.
242---

✓ Good

Upload product photo via POST /v1/asset-uploads → poll GET /v1/asset-uploads/{job_id} until status == "success" → extract asset.id from the response → pass that exact ID into the autofill image field. Verify every image field has a confirmed asset.id before calling POST /autofills.


Raw lines 234 to 243
244## Gotcha: Embedding Canva CDN thumbnail URLs in markdown
246**Why it matters:** Canva's autofill response returns short-lived,
247authenticated CDN URLs from `design.canva.ai`. These expire within minutes.
248If Claude embeds them as markdown images (`![](design.canva.ai/...)`), they
249render as broken "Show Image" placeholders by the time the message is shown.

Gotcha: Embedding Canva CDN thumbnail URLs in markdown

Why it matters: Canva's autofill response returns short-lived, authenticated CDN URLs from design.canva.ai. These expire within minutes. If Claude embeds them as markdown images (![](design.canva.ai/...)), they render as broken "Show Image" placeholders by the time the message is shown.

Raw lines 244 to 250
251### ✗ Bad
253Generate 8 designs → manually embed each CDN thumbnail URL in the response
254as `![Hero 1](https://design.canva.ai/xxx)` → all images show as broken
255gray placeholders because the URLs expired before render.

✗ Bad

Generate 8 designs → manually embed each CDN thumbnail URL in the response as ![Hero 1](https://design.canva.ai/xxx) → all images show as broken gray placeholders because the URLs expired before render.

Raw lines 251 to 256
257### ✓ Good
259Either let the native Cowork carousel render the tool result automatically,
260or export each design via `POST /exports` and embed the **permanent** export
261URL. As a final fallback, link to the design's permanent edit URL
262(`https://www.canva.com/d/{design_id}`). Never re-embed `design.canva.ai`
263URLs.
265---

✓ Good

Either let the native Cowork carousel render the tool result automatically, or export each design via POST /exports and embed the permanent export URL. As a final fallback, link to the design's permanent edit URL (https://www.canva.com/d/{design_id}). Never re-embed design.canva.ai URLs.


Raw lines 257 to 266
267## Gotcha: Listing designs one-by-one as individual image blocks
269**Why it matters:** When Claude lists each design as a separate block
270("Hero 1 / [image] / Hero 2 / [image]"), the images render as broken
271gray "Show Image" placeholders. Presenting all designs together in a
272single grouped batch triggers Cowork's side-by-side carousel, which
273renders correctly.

Gotcha: Listing designs one-by-one as individual image blocks

Why it matters: When Claude lists each design as a separate block ("Hero 1 / [image] / Hero 2 / [image]"), the images render as broken gray "Show Image" placeholders. Presenting all designs together in a single grouped batch triggers Cowork's side-by-side carousel, which renders correctly.

Raw lines 267 to 274
275### ✗ Bad
277```
278Hero 1 — Multi-property portfolio
279[Show Image]
280View in Canva: https://canva.com/d/xxx
282Hero 2 — Coastal market case study
283[Show Image]
284View in Canva: https://canva.com/d/yyy
285```

✗ Bad

Hero 1 — Multi-property portfolio
[Show Image]
View in Canva: https://canva.com/d/xxx

Hero 2 — Coastal market case study
[Show Image]
View in Canva: https://canva.com/d/yyy
Raw lines 275 to 286
287### ✓ Good
289Present all designs in one grouped response so they render as a
290side-by-side carousel. Below the carousel, add a single prompt:
292```
293Here are 4 hero designs for Week 1. Scroll through the carousel
294above and let me know which one to keep.
295```
297---

✓ Good

Present all designs in one grouped response so they render as a side-by-side carousel. Below the carousel, add a single prompt:

Here are 4 hero designs for Week 1. Scroll through the carousel
above and let me know which one to keep.

Raw lines 287 to 298
299## Gotcha: Generating designs sequentially instead of in parallel
301**Why it matters:** Generating designs one at a time means the owner waits
302through N round trips instead of one. Fire all generation requests within a
303batch at once and present selection after all jobs complete.

Gotcha: Generating designs sequentially instead of in parallel

Why it matters: Generating designs one at a time means the owner waits through N round trips instead of one. Fire all generation requests within a batch at once and present selection after all jobs complete.

Raw lines 299 to 304
305### ✗ Bad
307Generate design 1 → wait → show it → generate design 2 → wait → show it →
308… × 8 designs. Owner watches a slow drip for 10 minutes.

✗ Bad

Generate design 1 → wait → show it → generate design 2 → wait → show it → … × 8 designs. Owner watches a slow drip for 10 minutes.

Raw lines 305 to 309
310### ✓ Good
312Fire all designs in the current batch at once → poll all jobs concurrently →
313once all complete, export each → verify visually → then present.
315---

✓ Good

Fire all designs in the current batch at once → poll all jobs concurrently → once all complete, export each → verify visually → then present.


Raw lines 310 to 316
317## Gotcha: Auto-selecting a brand template for Pro/Teams users
319**Why it matters:** Pro/Teams users have no brand-template API access. If
320Claude guesses a template by name and generates with the wrong one, the owner
321gets designs in the wrong colors/fonts and has to redo the work in Canva
322manually.

Gotcha: Auto-selecting a brand template for Pro/Teams users

Why it matters: Pro/Teams users have no brand-template API access. If Claude guesses a template by name and generates with the wrong one, the owner gets designs in the wrong colors/fonts and has to redo the work in Canva manually.

Raw lines 317 to 323
324### ✗ Bad
326```
327Found template "Square Post - Blue". Using this for all feed posts.
328```
329…followed by 8 designs in blue when the brand is green.

✗ Bad

Found template "Square Post - Blue". Using this for all feed posts.

…followed by 8 designs in blue when the brand is green.

Raw lines 324 to 330
331### ✓ Good
333```
334I found 3 templates in your Canva library that could work for feed posts:
3351. Square Post - Blue (last edited March 2026)
3362. Summer Promo - Green (last edited April 2026)
3373. Product Feature Card (last edited Jan 2026)
339Which one should I use?
340```
342---

✓ Good

I found 3 templates in your Canva library that could work for feed posts:
1. Square Post - Blue  (last edited March 2026)
2. Summer Promo - Green  (last edited April 2026)
3. Product Feature Card  (last edited Jan 2026)

Which one should I use?

Raw lines 331 to 343
344## Gotcha: Caption voice drift across a long calendar
346**Why it matters:** When drafting 12–20 captions in one pass, the tone tends
347to drift — early captions follow the brief's voice markers, later ones slip
348into generic marketing copy. Owners notice immediately.

Gotcha: Caption voice drift across a long calendar

Why it matters: When drafting 12–20 captions in one pass, the tone tends to drift — early captions follow the brief's voice markers, later ones slip into generic marketing copy. Owners notice immediately.

Raw lines 344 to 349
350### ✗ Bad
352Post 1: "Our handmade candles are the perfect summer gift 🌿" (matches brief: "warm, conversational")
353Post 10: "Elevate your ambiance with our artisanal fragrance collection." (corporate drift)

✗ Bad

Post 1: "Our handmade candles are the perfect summer gift 🌿" (matches brief: "warm, conversational") Post 10: "Elevate your ambiance with our artisanal fragrance collection." (corporate drift)

Raw lines 350 to 354
355### ✓ Good
357Before drafting, anchor on 2–3 voice markers from the brief (e.g., "casual,
358friendly, uses light humor"). Re-read the first draft caption before writing
359each new one. If the owner flags a voice mismatch on any caption, re-read that
360caption and flag it as the recalibration point for the remaining drafts.
362---

✓ Good

Before drafting, anchor on 2–3 voice markers from the brief (e.g., "casual, friendly, uses light humor"). Re-read the first draft caption before writing each new one. If the owner flags a voice mismatch on any caption, re-read that caption and flag it as the recalibration point for the remaining drafts.


Raw lines 355 to 363
364## Gotcha: Staging HubSpot posts without verifying `scheduledAt` is in the future
366**Why it matters:** HubSpot rejects posts with `scheduledAt` in the past with
367a validation error. If the calendar was built on an earlier date and the
368owner is only now staging, some dates may have passed.

Gotcha: Staging HubSpot posts without verifying scheduledAt is in the future

Why it matters: HubSpot rejects posts with scheduledAt in the past with a validation error. If the calendar was built on an earlier date and the owner is only now staging, some dates may have passed.

Raw lines 364 to 369
370### ✗ Bad
372Build calendar on April 1st for June posts → owner approves May 15th → try to
373stage without checking → post for "April 30th 10:00 AM" returns 400.

✗ Bad

Build calendar on April 1st for June posts → owner approves May 15th → try to stage without checking → post for "April 30th 10:00 AM" returns 400.

Raw lines 370 to 374
375### ✓ Good
377Before calling `POST /social/posts`, compare each `scheduledAt` against the
378current UTC time. If any post date has passed, surface it: "The post scheduled
379for April 30th has already passed. Should I skip it, or reschedule it to next
380week?"

✓ Good

Before calling POST /social/posts, compare each scheduledAt against the current UTC time. If any post date has passed, surface it: "The post scheduled for April 30th has already passed. Should I skip it, or reschedule it to next week?"

Raw lines 375 to 380