← All Pull Requests

Classify unsupported native Field updates without hiding uncertain outcomes #19

Merged opened by John Lauer 2026-09-18
Merges astra/field-unsupported → master

Follow-up to the confirmed native failure in PR #18. Classify exactly ISC_INVALID_TYPE + PCB_FIELD_T + unhandled as native_field_update_unsupported, with kicadVersion and retryable:false, only when the transaction has confirmed rollback (mutated:false). Unknown rollback/commit outcomes and unrelated invalid-type errors retain their original semantics. The doc now states that KiCad 10.0.5 cannot perform this live field write and describes the explicitly disclosed saved-file/reload alternative without promising native Undo.

Base 09b813fb88b5d5280aaeb1c049f32056190d6786 (1.0.28), two focused files, no module/verb removals. Production cargo check and 263 tests pass (26 bridge +237 core), including exact error classification and preservation of uncertain outcomes. Native trigger evidence is your PR #18 acceptance; this mapper has source tests but has not been rerun on Windows. No shared runtime replaced.

Diff Skip to comments (1)

docs/native-silk-fields.md+6
@@ -14,3 +14,9 @@ Owner's native acceptance before publication: - Inspect post-commit errors without blindly replaying an edit. Refresh the exact linked views if necessary, then visually verify; a refresh acknowledgement does not prove rendering completed.  This is a contribution for #104's field-editing portion only. Exact mask/body obstacles, native model editing and reference camera framing remain separate features.++## Confirmed KiCad 10.0.5 limitation++Native acceptance of PR #18 on ConfRoomROG established that nested Field UUID lookup and dry-run DRC work, but UpdateItems rejects PCB_FIELD_T with ISC_INVALID_TYPE/unhandled. The transaction rolls back unchanged. This is not working live field editing on that version. That exact error is reported as `native_field_update_unsupported`, with the KiCad version and `retryable:false`, only after confirmed rollback. Unknown commit/rollback outcomes retain their original uncertainty and must be inspected.++The available alternative on 10.0.5 is an explicitly disclosed saved-file edit, not a live IPC mutation. Save/read the exact current board first, preserve a copy and all unrelated data, edit only the intended field geometry, run native DRC, then reload the correct editor and inspect the 2D and 3D results. Never overwrite unsaved work, silently substitute another board, or promise a native Undo transaction for this alternative. The bridge does not perform that fallback automatically.
rust/crates/kicad-core/src/ipc/silk_fields.rs+43−1
@@ -2,6 +2,21 @@ use super::*; use crate::silk_fields as fields; use kicad_ipc_rs::FieldItem; +fn classify_field_failure(mut error: RoutingError, version: &str) -> RoutingError {+    if error.code == "mutation_rolled_back"+        && error.detail.get("mutated") == Some(&json!(false))+        && error.message.contains("ISC_INVALID_TYPE")+        && error.message.contains("PCB_FIELD_T")+        && error.message.contains("unhandled")+    {+        error.code = "native_field_update_unsupported".into();+        error = error.with("kicadVersion", json!(version))+            .with("retryable", json!(false))+            .with("_hint", json!("This KiCad IPC server can read fields but cannot update Field payloads. The transaction rolled back. Do not retry as a transient failure or replace whole footprints. On KiCad 10.0.5, use an explicitly disclosed saved-file edit on a saved copy, then reload the exact editor and verify both views, DRC and preservation; that is not a live IPC edit."));+    }+    error+}+ fn id(item: &EditablePcbItem) -> Option<&str> {     match item {         EditablePcbItem::Field(f) => f@@ -144,7 +159,8 @@ pub fn silk_fields_batch(ctx: &Ctx, args: &Value) -> RResult<Value> {             ));         }         Ok(())-    })?;+    })+    .map_err(|e| classify_field_failure(e, &s.version.full_version))?;     let mut out = json!({"success":true,"committed":true,"mutated":true,"undoSteps":1,"updatedIds":ids,"footprintIds":plan.edits.iter().map(|e|&e.footprint_id).collect::<Vec<_>>(),"saved":false,"drc":after,"_hint":"Only nested reference/value fields were updated; no whole footprint replacement. Inspect postCommit errors before any retry, then refresh the exact linked views and inspect the board."});     match s.client.get_editable_items_by_id(ids.clone()) {         Ok(actual) => {@@ -206,6 +222,32 @@ pub fn silk_fields_batch(ctx: &Ctx, args: &Value) -> RResult<Value> { mod tests {     use super::*;     #[test]+    fn unsupported_field_is_permanent_only_after_confirmed_rollback() {+        let message =+            "ISC_INVALID_TYPE: Tried to create an item of type PCB_FIELD_T, which is unhandled";+        let e = classify_field_failure(+            RoutingError::new("mutation_rolled_back", message).with("mutated", json!(false)),+            "10.0.5",+        );+        assert_eq!(e.code, "native_field_update_unsupported");+        assert_eq!(e.detail["retryable"], false);+        assert_eq!(e.detail["kicadVersion"], "10.0.5");+        for code in ["mutation_outcome_unknown", "ipc_timeout"] {+            let e = classify_field_failure(+                RoutingError::new(code, message).with("mutated", Value::Null),+                "10.0.5",+            );+            assert_eq!(e.code, code);+            assert_eq!(e.detail["mutated"], Value::Null);+        }+        let e = classify_field_failure(+            RoutingError::new("mutation_rolled_back", "ISC_INVALID_TYPE: other type")+                .with("mutated", json!(false)),+            "10.0.5",+        );+        assert_eq!(e.code, "mutation_rolled_back");+    }+    #[test]     fn nested_field_uuid_and_content_survive_geometry_update() {         let mut f = FieldItem::from_proto(Default::default());         let p = f.proto_mut();

Comments

John Lauer 2026-09-18

Merged on the wiki (99b778d), shipped as KiCad Bridge 1.0.29 (insiders), and provoked on ConfRoomROG (KiCad 10.0.5) with the same R26 Reference update that failed under PR #18:

errorCode     native_field_update_unsupported
kicadVersion  10.0.5
retryable     false
mutated       false
error         item request status error `ISC_INVALID_TYPE: Tried to create an item of type PCB_FIELD_T, which is unhandled`

Revision unchanged afterwards, so the rollback held and the classification fires only where it should. The classifier test covers the two uncertain codes keeping their own semantics, which is the part that matters most. Closing.

Log in to comment.