You painted a terrain.
One cell came out wrong.

A corner piece in the middle of a field, an edge facing the wrong way. Page 1 gives you two answers that cannot both be true — "it picks the closest match" and "the algorithm is non-deterministic" — and neither one measures anything. On Godot 4.7 the painting is deterministic, it will never leave the cell empty, and it will never borrow from another terrain. So the wrong tile almost always means your set has no tile for that neighbourhood, and the engine substituted one without telling you. Paint a region below and find the cell.

Click cells to paint and unpaint. Each painted cell shows the neighbourhood it asks the engine for.

 painted  no tile in your set — the engine substitutes one  rewritten when the second chunk arrives

    The short answer

    Terrain painting in 4.7 picks the tile that disagrees with the fewest peering bits, restricted to tiles that belong to the terrain you are painting. It will not leave the cell empty and it will not borrow from a neighbouring terrain. That is the whole reason you see a wrong tile instead of an error: the engine would rather give you an ugly tile of the right terrain than no tile at all.

    Every claim below carries an id (T1, T4, …) asserted by verify_terrain_choice.gd, which re-runs the lot against your Godot build and exits non-zero if any of it stops holding. 24 checks, measured 2026-08-18 against 4.7.stable.official.5b4e0cb0f.

    It is not random

    The "non-deterministic" claim does not reproduce. Four ways of asking:

    idwhat was doneresult
    T1the same paint repeated 30× in 30 fresh layers1 distinct tile
    T2the same cells passed in reversed array ordersame tile
    T3the region painted cell-by-cell vs all at oncesame tiles
    T1330× repeat of a neighbourhood with no exact match1 distinct tile
    T1920× repeat with the needed tile deleted from the atlas1 distinct tile

    Same input, same output — including in the ambiguous cases, which is exactly where a random tie-break would show up if there were one.

    You can predict how wrong it will be. You cannot predict which wrong tile.

    Take the complete 47-tile blob set and delete the one tile that means "surrounded on all eight sides" (mask 255). Paint a 3×3 block, whose centre needs exactly that tile. The centre is still painted (T17) — no error, no warning. It gets the tile with mask 247:

    wanted:  255  = N NE E SE S SW W NW
    placed:  247  = N NE E    S SW W NW      (247 = 255 - 8, the SE corner bit)
                            ^^ one bit off

    One bit off is the best any remaining tile can do (T18). But 247 is not the only tile that scores 1: so do 127, 223 and 253, and the engine's choice among those four is not explained by the score. Sweeping the whole set — knock out each of the 47 tiles in turn and ask for exactly the neighbourhood it answered:

    idover all 47 holesresult
    T20is the substitute always a minimum-mismatch tile?47 of 47 — yes, every time
    T21how often does exactly one tile reach that minimum?0 of 47. Between 3 and 8 tiles tie

    So the score tells you how wrong the substitute will look, and never which of the tied tiles you get. It is not the lowest-numbered one (2 of 47) and not the first one in the atlas (7 of 47). The tool at the top of this page reports the score and the tie set for that reason, and deliberately refuses to name a tile — a predictor that guessed would be right about a third of the time and unfalsifiable the rest.

    An earlier version of this write-up said "exactly one tile ties at 1", citing T18. T18 never asserted that: its note printed how many times one mask appeared in an array, which in a set without duplicate tiles is always 1. The sweep above is what replaced it, and the note now counts ties properly.

    The same rule with a sides-only set (T12): the fallback still matches every side the neighbourhood asked for, and only ever gives up corner information.

    It never reaches into another terrain

    There is a well-travelled issue titled "TileMap Terrain paints incorrect tiles from unrelated terrains". On 4.7 we could not make that happen.

    If your terrain looks like it borrowed a tile from a neighbour, check whether those tiles are assigned to the terrain you think they are. A peering bit holds a terrain index, not a boolean — = 0 means terrain 0, and a bit pointing at another terrain looks set in the inspector while counting for somebody else.

    The empty cells around what you painted are constraints

    This is the most common surprise, and it is not a bug. Paint a 3×3 block on an empty layer: the centre gets the fully-surrounded tile (T4) and the corner does not (T5).

    corner (0,0):  mask 28   = E SE S          — an outer-corner tile
    edge   (1,0):  mask 124  = E SE S SW W     — a top-edge tile
    centre (1,1):  mask 255                    — fully surrounded

    The empty cells outside the block count as "not this terrain", so the border of anything you paint gets edge tiles. If you generate a map in chunks, the seam between two chunks is painted against emptiness and then rewritten when the neighbouring chunk arrives (T9). Switch the tool above to left half first, then the rest and the rewritten cells are outlined. Paint the whole region in one call, or accept that borders are provisional.

    ignore_empty_terrains does not turn that off

    set_cells_terrain_connect() takes a 4th argument, ignore_empty_terrains, and it is the first thing people reach for here. In three constructions it changed nothing on 4.7: neighbours with no tile at all → 0 of 9 cells differ (T6); neighbours holding a tile of no terrain → no difference; the only exact match belonging to no terrain → no difference (T7).

    Honest limit: a negative result is not proof that the flag does nothing. It means we could not build a case on 4.7 where it bites, and the three obvious readings of its name are all wrong. If you have a repro where it changes the output it belongs in an issue on the repo, and it becomes a fixture. What we can say is: if you are chasing a wrong border tile, this flag is not the lever.

    The terrain mode decides what is knowable

    A terrain set has a mode, and it silently caps what your tiles can express:

    modebits useddistinct neighbourhoods
    MATCH_CORNERS_AND_SIDESall 847
    MATCH_SIDES4 sides16
    MATCH_CORNERS4 corners16

    A sides-only set paints all 256 neighbourhoods without complaint (T10) and can only ever produce its own 16 tiles (T11). It is not broken and not incomplete — it cannot see corners, so every corner-only difference collapses to the same tile. If you drew 47 tiles and the set is in sides mode, 31 of them are unreachable and nothing will tell you. Pick sides-only in the tool above and watch the neighbourhood numbers collapse.

    (There is no is_valid_terrain_peering_bit() on TileSet in 4.7 — asking a sides-only set for a corner bit is an engine error, not a zero. Derive the valid bits from get_terrain_set_mode(), as the script does.)

    So: why is my tile wrong?

    In the order worth checking:

    1. Your set has no tile for that neighbourhood. By far the most common. The engine substitutes silently, so the only way to see it is to sweep — which is what the tool above does for the region you paint, and what the 47-tile page does for the set as a whole.
    2. The terrain mode does not match the sheet you drew. 16 vs 47.
    3. The peering bits are painted wrong on the tile. The classic advice, and the one page 1 gives — it is real, just third in line.
    4. The cell is on the border of what you painted, against empty cells. Not a bug; see above.

    Run it on your own project

    Two free MIT scripts in the Blobsmith Autotile Wirer repo, no dependencies, nothing to install:

    # the predictor this page runs, in your terminal — no engine needed
    node docs/predict_terrain_paint.js your_tileset.tres --rect 5x3 --chunks
    
    # and the 24 claims above, re-asserted against YOUR Godot build
    godot --headless --script docs/verify_terrain_choice.gd -- res://your_tileset.tres res://sides16.tres

    The predictor exits 1 if any cell of the region has no exact tile in your set, so it drops into a build script. The verifier prints PASS/FAIL per claim and exits non-zero if any stops holding — point it at a newer Godot and it tells you exactly which line of this page changed. Omit the second argument and the six claims that need a sides-only set print SKIP; the rest still run and still gate the exit code.

    The predictor in this page is the same file the terminal runs, byte for byte — terrain-choice-core.js. A test refuses to ship this page if the copy served here has drifted, and a second test replays 258 cells of engine-measured output (terrain-paint-fixtures.json, dumped straight out of Godot) and fails if the predictor disagrees on one of them. Full write-up: why-terrain-paints-the-wrong-tile.md.

    Which tool owns which half

    Being straight about this, since most of what is above is your TileSet and not our software: