Skip to content

Commit 0471ac6

Browse files
TMHSDigitalclaude
andauthored
fix(skills): name the silent bake failure and check the bake result (#429)
bake-high-to-low said a missing UV layer or a non-active image node "finishes without error". Measured on 4.5.11 LTS and 5.2.1 LTS: a missing UV layer raises RuntimeError, a lone Image Texture node that is not nodes.active is baked into anyway, and the case that really is silent is a material with no Image Texture node, which returns {'CANCELLED'} and raises nothing. The canonical call assigned `result` and never looked at it. The skill now tabulates the three measured behaviours, and both the skill's canonical call and snippets/bake_normal_high_to_low.py raise when the result is not {'FINISHED'}. Closes #356 Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent f30667e commit 0471ac6

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

‎skills/bake-high-to-low/SKILL.md‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@ This skill is the bake step. It composes `ai-mesh-cleanup` (identity scale, appl
1919

2020
## The core misunderstanding
2121

22-
Baking is not a render. EEVEE has no bake path. The operator writes into the **active Image Texture node** of the **active** object's material, not into a file and not into "the selected image datablock." A missing UV layer, the wrong object active, or a node that is not `nodes.active` finishes without error and leaves a blank or unchanged image.
22+
Baking is not a render. EEVEE has no bake path. The operator writes into an **Image Texture node** in the **active** object's material (the active one, `nodes.active`, when the material has several), not into a file and not into "the selected image datablock." The failure modes are not equally loud. Measured on 4.5.11 LTS and 5.2.1 LTS:
23+
24+
| Setup mistake | What `bpy.ops.object.bake` does |
25+
| --- | --- |
26+
| Target mesh has no UV layer | Raises `RuntimeError: No active UV layer found in the object "Low"` |
27+
| Target material has no Image Texture node | Returns `{'CANCELLED'}`, **raises nothing**, writes nothing |
28+
| The only Image Texture node is not `nodes.active` | Bakes into it anyway (`{'FINISHED'}`) |
29+
30+
So a headless job must check the returned set: `{'CANCELLED'}` is the silent one. With several Image Texture nodes, set `nodes.active` to the one you mean.
2331

2432
The pass type RNA is `type`, not `bake_type`. `bake_type` is not on `bpy.ops.object.bake`. Passing it is a TypeError.
2533

@@ -104,6 +112,9 @@ result = bpy.ops.object.bake(
104112
use_clear=True,
105113
target="IMAGE_TEXTURES",
106114
)
115+
if result != {'FINISHED'}:
116+
# {'CANCELLED'} raises nothing: e.g. no Image Texture node in the material.
117+
raise RuntimeError(f"bake did not finish: {result}")
107118
```
108119

109120
`cage_extrusion` inflates the active object along its normals so rays hit the high mesh. It must clear the high-frequency amplitude (ribs at 0.10 need extrusion > 0.10; 0.20 is the worked value). If extrusion alone skims past concavities, set `use_cage=True` and `cage_object="CageName"` (the object's `.name`). Do not pass the Object.

‎snippets/bake_normal_high_to_low.py‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# normal map. Cycles CPU only. High must be selected; low must be active.
33
# Operator RNA is `type`, not `bake_type`. cage_object is a string name.
44
# Identifiers match on 4.5 LTS, 5.1, and 5.2 LTS — no version shim.
5+
# A missing UV layer raises, but a material with no Image Texture node
6+
# returns {'CANCELLED'} without raising, so check the result.
57
#
68
# Reference:
79
# https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.bake
@@ -18,7 +20,7 @@ def bake_normal_high_to_low(high, low, cage_extrusion=0.20, margin=16):
1820
high.select_set(True)
1921
low.select_set(True)
2022
bpy.context.view_layer.objects.active = low
21-
return bpy.ops.object.bake(
23+
result = bpy.ops.object.bake(
2224
type="NORMAL",
2325
use_selected_to_active=True,
2426
cage_extrusion=cage_extrusion,
@@ -29,3 +31,6 @@ def bake_normal_high_to_low(high, low, cage_extrusion=0.20, margin=16):
2931
use_clear=True,
3032
target="IMAGE_TEXTURES",
3133
)
34+
if result != {"FINISHED"}:
35+
raise RuntimeError(f"bake did not finish: {result}")
36+
return result

0 commit comments

Comments
 (0)