"The G-Code Looks Correct, But the Machine Does Something Wrong" — Here's Why

It is one of the most frustrating sentences in CNC machining:

"The simulation in Fusion looks perfect. But on the machine, it crashed."

Or its variants:

"The G-code looks right to me, but the machine went the wrong way." "The toolpath is correct, but I'm getting an alarm on the arc." "The program ran fine last week, but now it's doing something unexpected after the tool change."

These are not beginner mistakes. They happen to experienced programmers on proven machines with well-configured setups. They happen because there is a gap between what CNC programming tools show you and what the machine actually executes — and that gap is structural, not accidental.

This article explains why that gap exists, what causes it, and how to close it before it becomes a crash.


The Core Problem: Two Different Things Called "Simulation"

When a CNC programmer says "the simulation looks correct," they almost always mean the CAM simulation — the animation inside Fusion 360, Mastercam, or whatever CAM system they use.

When the machine does something wrong, the cause is almost always in the G-code — the posted file that runs on the controller.

These are not the same thing, and the distance between them is where most unexplained machine behavior originates.

CAM simulation simulates the toolpath. It does not simulate the G-code.

The CAM system plans cutter movements in a geometry-neutral internal format. It verifies that those movements produce the intended part shape. Then the post-processor converts those movements into machine-specific G-code. The CAM simulation runs before that conversion — so it shows you what you intended, not what the G-code will actually tell the machine to do.

Every error introduced by the post-processor, every incompatibility between the posted code and the specific controller on your machine, every modal state interaction that depends on what the controller was doing before your program started — none of these appear in the CAM simulation. They are invisible by design, because the CAM simulator does not read the G-code file.

The machine, however, reads nothing else. It executes the G-code literally, character by character, block by block, with no knowledge of your intent and no tolerance for the gap between what you meant and what you wrote.


The Seven Most Common Causes of "Looks Correct, Runs Wrong"

1. Incompatible IJK Arc Format

Circular interpolation (G02/G03) can be defined in two ways: using a radius value (R) or using the incremental distance from the arc start point to the arc center (I, J, K). Both are valid in theory. In practice, different controllers handle them differently, and incompatible arc definitions are one of the most common sources of alarms and unexpected geometry.

Common scenarios:

  • IJK sign convention mismatch. Some controllers expect I, J, K to be signed incremental values from the arc start point to the center. Others expect them unsigned, or absolute, or measured from the end point. A post-processor configured for one convention running on a controller that expects another produces arcs that alarm out or cut the wrong geometry — while looking perfectly correct in the CAM simulation, which has no concept of controller-specific arc conventions.
  • Plane mismatch. G02/G03 arcs execute in the currently active plane (G17 for XY, G18 for XZ, G19 for YZ). If the plane declaration is missing, incorrect, or inherited from a previous program or operation, an arc that expects I/J values will be executed in a plane where I/K or J/K are the relevant addresses instead. The result is an alarm or an arc that cuts in the wrong plane entirely.
  • R-format incompatibility. A post configured to output R-format arcs (G02 X50. Y40. R25. F800.) may be running on a controller that only accepts IJK format, or that handles R-format arcs differently for arcs larger than 180 degrees. The CAM simulation renders the arc correctly regardless of which format was used in the G-code.

2. G43 / Tool Length Compensation Errors

G43 activates tool length offset compensation, applying the length stored in the controller's tool table to Z-axis positioning. It is the bridge between the Z coordinates in your program and the actual position of the tool tip relative to the workpiece.

When G43 goes wrong, the consequences range from producing the wrong part to crashing the spindle into the fixture.

  • Missing G43 block. If length compensation is not activated before the first Z move toward the part, the controller uses the machine gauge line — the spindle nose — as the Z reference instead of the tool tip. Depending on tool length, this can send the tool 50 to 200mm below where the program expects it to be.
  • Wrong H address. G43 H01 applies the offset stored in tool position 1 of the tool table. G43 H02 applies a different offset. A post-processor that outputs the wrong H number — or a program where the H address and the T number have become mismatched during editing — applies an incorrect Z compensation to every move in that operation. The CAM simulation has no tool table to reference; it assumes the correct offset is applied and shows the program running correctly regardless.
  • G43 applied after the first Z move. The sequence G00 Z50. followed by G43 H01 Z45. on the next line applies length compensation during a Z move that is already in progress. Depending on the controller, this can cause a sudden unexpected Z shift during motion, potentially crashing into the workpiece or fixture. The correct sequence is to activate G43 before the first Z move toward the part.
  • G49 canceling compensation at the wrong moment. G49 cancels tool length compensation. If a post-processor outputs G49 between operations when the tool is still within the work envelope, the next Z move loses compensation and the tool position becomes unpredictable.

3. Work Offset Errors (G54-G59)

Work offsets (G54 through G59, and their extensions G54.1 P1-P48 on Fanuc) define where the part origin is in machine coordinates. They are the spatial reference that connects your program coordinates to the physical location of the part on the machine.

  • Wrong offset called in the program. A program written for G54 running on a machine where G54 and G55 have been swapped, or where G54 has not been set for the current setup, will position the tool relative to a completely different reference point. The machine moves — the moves look intentional and deliberate — but they are all wrong by the exact distance between where the part actually is and where G54 says it is.
  • Offset not set for the current operation. When a program references a work offset that has never been configured on the controller, the machine uses whatever value is stored — which may be zero, which may be a previous job's setup, or which may be a value entered during a different operation. All of these produce unexpected positioning.
  • Modal offset inherited from a previous program. CNC controllers are stateful. The work offset active when one program ends is still active when the next program starts, unless the new program explicitly declares its own. A program that assumes G54 is active because that is what the programmer set up may run in G55 if the previous program ended with a G55 call and the operator did not reset the control state.

The CAM simulation has no controller state. It simulates each program in isolation, with the work offset set exactly as programmed, with no inherited modal conditions from previous programs. The machine has no such isolation.

4. Unexpected Rapid Moves

G00 (rapid traverse) moves the tool at the maximum speed the machine can achieve on each axis simultaneously, with no feed rate override and no coordinated path guarantee. On machines with different maximum speeds per axis, a G00 move to X100. Y100. Z50. moves each axis at its own maximum rate — the resulting path is not a straight line, and the tool passes through intermediate positions that are not shown in a simple CAM backplot.

  • Rapid moves through fixtures. A retract that clears the workpiece may pass through a clamp, a vise jaw, or a fixture component at an intermediate position during a multi-axis rapid. The endpoint is safe. The path is not. The CAM simulation often renders rapid moves as straight lines regardless of actual axis behavior.
  • Post-processor inserting unexpected rapid moves. Some post-processors insert automatic retract or return moves between operations — moves that are not part of the CAM toolpath and are not visible in the CAM simulation. These are generated by the post to manage tool changes, safe heights, or return-to-home sequences. If the post-processor's safe height assumptions do not match the actual fixture geometry, these automatic moves can crash into components that the programmer never considered, because they were never visible in the simulation.
  • G00 with active incremental mode. If G91 (incremental mode) is active — inherited from a previous program block or a previous program — a G00 move to what appears to be an absolute position actually moves the specified distance from the current position. A rapid to G00 Z100. that should retract to Z100 machine coordinates instead moves 100mm upward from wherever the tool is, which may be well below the fixture, well above the safe zone, or into a hard limit.

5. Tool Change at the Wrong Position

Automatic tool changes (M06) require the spindle to be at the tool change position — typically Z machine home or a specific ATC position — before the change executes. The sequence for getting there, and the state of the machine during and after the change, is entirely controlled by the post-processor and the machine macro that executes M06.

  • Missing or incorrect Z retract before tool change. If the post-processor does not generate a sufficient Z retract before M06, or if the retract move uses a work coordinate that places Z home in an unsafe position relative to the fixture, the machine attempts to move to the tool change position while the spindle is still within the work envelope. The result is a collision between the tool, holder, and fixture during what appears in the CAM simulation to be a normal, routine tool change.
  • Post-generated positioning moves after tool change. After M06, most post-processors generate a move to a safe position before beginning the next operation — typically a rapid to a clearance height and then to the first XY position of the next operation. If this positioning move uses work coordinates and the next operation's work offset has not yet been activated, the move positions the tool relative to the wrong reference, potentially driving it into the fixture.
  • M06 with spindle running. On some machines, the spindle must be stopped (M05) before a tool change. A post-processor that omits M05 before M06 on a machine that does not auto-stop the spindle at tool change generates a macro alarm or, on older machines, attempts a tool change with the spindle rotating — which is mechanically catastrophic.

6. M-Codes Not Supported by the Controller

M-codes are machine-specific. Unlike G-codes, which follow a relatively consistent standard across controllers, M-codes vary significantly between machine builders, controller generations, and machine configurations. An M-code that means "activate coolant" on one machine may be undefined on another, or may activate a completely different function.

  • Generic post-processor M-codes. A post-processor written for a generic Fanuc or Haas controller may output M-codes that are standard for that controller family but are not configured on a specific machine. On most controllers, an undefined M-code produces an alarm. On some older controllers, an undefined M-code is silently ignored — meaning a coolant activation, a chip conveyor start, or a pallet change command simply does not execute, with consequences that depend on what that function was supposed to do.
  • M-code conflicts with machine-specific macros. Machine builders often assign M-codes to custom functions — special fixture clamping, automatic door operation, probing routines, part counters. If a post-processor outputs an M-code that the machine builder has assigned to a different function than what the post expects, the machine executes the builder's function instead. This is particularly common when using generic posts on specialized machines or when a machine has been retrofitted with additional functionality.

7. Modal State Inherited from a Previous Program

CNC controllers maintain their state between programs. When a program ends with M30, the controller does not reset all modal codes to their defaults. The plane selection, compensation modes, coordinate mode, and active work offset remain as they were when the program ended, until explicitly changed.

  • G91 inherited from a previous run. If the previous program ended with incremental mode active (G91) and the new program does not explicitly declare G90 at the start, every coordinate in the new program is interpreted as incremental from the current position. A Z move to Z100. becomes "move 100mm in Z from where you are now" rather than "move to Z100 in the current coordinate system." Depending on where the tool is when the new program starts, this can immediately drive the tool into the workpiece, the fixture, or the machine structure.
  • Active canned cycle not canceled. Drilling and tapping canned cycles (G81, G83, G84, and their variants) remain active until canceled with G80. If a program ends without G80 and the next program includes Z moves without explicitly canceling the canned cycle, those Z moves may be interpreted as drill cycle executions rather than positioning moves.
  • Cutter radius compensation not canceled. G41/G42 (cutter radius compensation) modifies the tool path by the tool radius to account for tool size in 2D contouring. If compensation is active when a program ends and the next program begins moving without G40 to cancel it, the initial moves of the new program are modified by an offset the programmer never intended.

None of these modal state conditions are visible in the CAM simulation, which simulates each program in isolation with a clean initial state. The machine has no concept of a "clean initial state" — it simply continues from wherever the previous program left it.


Why This Is Not a Programming Error

The natural reaction to this list is to conclude that better programming discipline — explicit modal declarations, standardized program headers, careful post-processor configuration — eliminates these problems. And it does reduce them.

But it does not eliminate them, for one fundamental reason: the interaction between your G-code and your specific controller on your specific machine in its current state cannot be fully predicted without simulating that interaction.

A program that runs correctly on one Fanuc 18i may fail on a Fanuc 0M because the two controllers handle a specific modal default differently. A post-processor that has been working correctly for two years may produce an unexpected result when the CAM software updates its post engine. A program that proved out cleanly last month may behave differently this month if an operator changed a controller parameter.

The only way to catch these interactions before they reach the machine is to simulate the actual G-code — not the CAM toolpath, but the posted file — against a model that includes the machine's controller behavior, the current tool table, the fixture geometry, and the work coordinate system.


Closing the Gap with G-Code Simulation

Eureka 3X Pro simulates the actual posted G-code against a digital twin of your 3-axis CNC machine. Not the toolpath. Not the CAM geometry. The .nc file that the machine will receive.

This means the simulation sees the same arc format the controller sees. It applies the same G43 H address to the same tool length. It activates the same work offset in the same coordinate system. It executes the tool change move through the actual fixture geometry at the actual machine position.

Every one of the seven failure modes described in this article is visible in Eureka before the program runs on the machine:

  • An IJK arc with the wrong sign convention appears as an incorrect arc geometry or an arc alarm in the simulation, not on the machine
  • A missing G43 block shows the tool plunging from the spindle nose reference, making the position error immediately visible
  • A wrong G54 reference positions the simulated tool in the wrong location relative to the workpiece model
  • A rapid move that passes through a fixture component appears as a collision in the simulation, with the exact block number and tool position identified
  • A tool change that does not retract sufficiently shows the collision between the holder and the fixture during the ATC sequence
  • An unsupported M-code is flagged in the simulation rather than executing silently or generating an alarm on the machine
  • An inherited G91 modal state, if present in the simulation's starting conditions, produces the same incorrect moves in the simulation that it would produce on the machine

When Eureka finds one of these problems, you pause the simulation, fix the G-code in the integrated editor, and resume from the same point. The corrected file is what gets loaded on the machine.

The machine runs the program that has already been verified. The gap between what the CAM showed you and what the machine will actually do has already been closed — at the computer, before the first chip.

Try Eureka 3X Pro free for 30 days — no credit card required. Start your free trial at eureka3x.com →


Frequently Asked Questions

If this is such a common problem, why doesn't the CAM software fix it? CAM software is designed to plan toolpaths and generate G-code. Simulating the interaction between that G-code and a specific controller is a fundamentally different problem — it requires modeling controller behavior, machine kinematics, tool table states, and coordinate system logic that varies by machine. This is what dedicated G-code simulators are built for. CAM vendors acknowledge this gap; Fusion 360's own documentation recommends verifying posted G-code separately from the CAM simulation.

My post-processor has been working for years without problems. Why should I worry? A post-processor that works reliably for a known set of programs may produce unexpected output when the program structure changes — new operations, different canned cycles, different arc types, or programs that interact with modal states in new ways. CAM software updates also periodically change post engine behavior. The programs most likely to expose post-processor edge cases are new programs or programs that use features the post hasn't been tested with before — which is exactly when verification matters most.

Does G-code simulation catch setup errors (wrong work offset entered by the operator)? G-code simulation catches errors in the program itself — wrong G54 call, wrong H address, missing G43. It does not catch errors in what the operator enters into the controller's offset tables, because those values are not known at simulation time. What simulation does is ensure that the program calls the correct offsets correctly — so if an operator enters a wrong value, the cause is clearly identified as a setup error rather than a programming error, which is faster and cheaper to diagnose.

Can I use Eureka 3X Pro with any CAM system? Yes. Eureka 3X Pro simulates the posted G-code file, not the CAM toolpath. It works with the output of any CAM system — Fusion 360, Mastercam, SolidCAM, hyperMILL, or any other — because it reads the standard NC file the post-processor generates, regardless of which CAM produced it.

What does "any 3-axis CNC machine" mean in practice? Eureka 3X Pro can be configured to model your specific machine's geometry, working envelope, axis travel limits, and tool table structure. "Any 3-axis machine" means the simulation is not limited to a predefined library of machine models — it can be set up to reflect the actual machine in your shop, with your actual fixture positions, your actual tooling, and your actual coordinate system configuration.