Resolving WinCC Unified OpenFaceplateInPopup Parse JSON Failed

David Krause12 min read
SiemensTroubleshootingWinCC
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Summary

The WinCC Unified Runtime Trace Viewer records the following diagnostic line every time a pop-up faceplate is opened from inside another faceplate:

session: 0010, trace: Parse JSON failed
90570 | ... | SIM_24220041_NEO_V106 | GfxRTS(22) | UAWebRHBase | GfxJSONFilter | Error | 2025.02.26 09:59:13.911970 | 50836 (0x9cf4) | session: 0010, trace: Parse JSON failed

Despite the trace entry, the HMI behaviour appears to be correct: the pop-up window opens with the expected faceplate instance, the user can interact with it, and closing the pop-up returns control to the parent screen. The error is a diagnostic message produced by the runtime JSON-serialization filter (component GfxJSONFilter) when it fails to build the payload that is forwarded to the faceplate proxy on the Unified Collaboration / Runtime back end.

The typical customer report pattern looks like this:

  • Engineer drags a Popup Screen window element into a screen and wires a button's Click event to a script that calls Faceplate.OpenFaceplateInPopup(...).
  • Trace Viewer shows red Error entries on every pop-up invocation.
  • Functional test passes; the engineer's first instinct is to ignore the trace.
  • The same code path silently breaks inheritance of interface data in nested faceplate types, so the underlying root cause must be understood and fixed.
Important: Even if the HMI appears to function, every Parse JSON failed entry represents a lost interface property assignment. If a faceplate instance later evaluates a property it expected to inherit (tags, dynamic texts, security state, or the Index of an array element) it may read an undefined or default value rather than the value coming from the parent faceplate. Treat the trace as a real defect, not informational noise.

Affected Versions and Environment

Component Versions Verified Notes
TIA Portal / WinCC Unified Engineering V17, V18, V19, V20 Both ES and RT share the same JavaScript object model. The OpenFaceplateInPopup method has been available since V17.
Unified Runtime (RT Unified) ≥ V17 Update 4 Earlier V17 builds exposed a single-argument signature. Always confirm the exact patch level on the Panel / PC target.
HMI devices Comfort/Mobile Panels with Unified firmware, Unified PC RT, OpenPipe Behaviour is identical across Unified Panel, Unified PC and OpenPipe runtime targets.
Sample project build tag SIM_24220041_NEO_V106 Internal Siemens build tag observed in the customer trace. TIA Portal V20 ships NEO_V106 as the standard image generation for WinCC Unified runtime.

Root Cause Analysis

The OpenFaceplateInPopup method exists in two scopes with two different signatures. The runtime serializer (GfxJSONFilter) builds a JSON payload that carries the pop-up parameters from the script context to the faceplate container. If the calling code does not supply all of the parameters that the serializer is hard-wired to emit, the resulting JSON object becomes malformed and parsing fails when the proxy on the receiving side attempts to deserialize the message.

Scope 1 — UI scope (document level)

Available globally on the screen, this is the method documented as UI.OpenFaceplateInPopup() in the WinCC Unified JavaScript reference. The signature in V20 is:

UI.OpenFaceplateInPopup(
  screenName     : String,
  parameters?    : Array<Variant>,
  modal?         : Boolean,
  position?      : Point,
  closeOnLostFocus? : Boolean
) : Screen

All parameters are documented as optional. When the call site is the UI scope, the JSON filter constructs a default parameter object from the screen configuration and the trace entry is not generated. The official reference is in the TIA Portal V20 cloud docs: UI.OpenFaceplateInPopup() (RT Unified) — TIA Portal V20.

Scope 2 — FaceplateType scope (the affected call)

When a script is written inside a faceplate type — for example in a button on the faceplate's root container — the Faceplate object exposes its own OpenFaceplateInPopup helper. The effective signature is:

Faceplate.OpenFaceplateInPopup(
  faceplateType : String,   // type name of the pop-up faceplate
  title?        : String,   // window title
  modal?        : Boolean,  // true = blocks input on the parent screen
  center?       : Boolean   // true = centres the pop-up on the screen
) : Screen

Although the documentation labels the last three arguments as optional, omitting them yields a parameter list that the JSON filter does not know how to serialize. The filter is hard-coded to emit four well-typed fields; it receives only one or two and writes a partial object into the wire payload. The receiver tries to parse the truncated message, the parser throws, and the runtime logs Parse JSON failed. The pop-up appears to open because the visual component is constructed before the JSON filter is invoked; the trace entry is logged on the property-inheritance roundtrip that follows.

Why interface data disappears

The FaceplateType scope also differs in how interface data is propagated. The parent faceplate's Properties (UDT, UDT_HMI, Index, SecurityNo, etc.) are inherited by the opened faceplate. If the JSON filter fails, the inheritance is broken for the missing keys. Code that relies on those keys reading the correct value will silently fall back to defaults. The same applies to Faceplate.Properties.UDT, Faceplate.Properties.UDT_HMI, and Faceplate.Properties.Index that are typically passed in via a let data = {...} block when the call site is the UI scope.

Solution

Always pass the full argument list when calling Faceplate.OpenFaceplateInPopup from within a faceplate type. The minimal corrected call is:

// INCORRECT — throws "Parse JSON failed" in Trace Viewer
Faceplate.OpenFaceplateInPopup("FP_pop_up_empty_V_0_0_2", title);

// CORRECT — all four arguments supplied, trace stays clean
Faceplate.OpenFaceplateInPopup("FP_pop_up_empty_V_0_0_2", title, true, false);

Argument semantics for the fix:

Position Parameter Type Recommended value Meaning
1 faceplateType String Name of the faceplate type as registered in the project (no path, no extension) The faceplate instance the pop-up will host
2 title String "Alarm overview", "Trend #" + Index, etc. Title of the pop-up window
3 modal Boolean true for confirmation dialogs, false for tool windows Block input on the parent screen
4 center Boolean true for ad-hoc dialogs, false when you manage position elsewhere Centre the pop-up on the screen
Note: The two-scope design is intentional. The UI scope can infer default modal/position values from the screen object. The FaceplateType scope cannot, because the faceplate container is owned by a different parent. The runtime must receive explicit values to emit a deterministic JSON payload.

Pattern for passing interface data to the child faceplate

Use the inherited Faceplate.Properties object so the child faceplate receives the same data the parent has — without re-typing it. The recommended pattern is:

// In the parent faceplate, e.g. on a button's Click event
let sTitle = "Detail — Item " + Faceplate.Properties.Index;
Faceplate.OpenFaceplateInPopup(
  "FP_PopUp_Empty_V_0_0_2",
  sTitle,
  true,   // modal
  false   // centered manually via screen coordinates
);

The child faceplate sees the UDT, UDT_HMI, Index, and SecurityNo inherited from the parent automatically. Do not attempt to pass an additional data object in the call — the FaceplateType signature does not support one, and doing so will trigger the same Parse JSON failed error.

Pattern when you need to forward a custom data set

If the application needs to forward non-interface data (for example, a temporary value computed in script), use a tag on the HMI as a side channel rather than a fifth argument:

Tags("PopupContext") = Faceplate.Properties.Index;
Faceplate.OpenFaceplateInPopup("FP_PopUp_Empty_V_0_0_2", title, true, false);

The child faceplate reads Tags("PopupContext") on its OnLoaded event. This pattern keeps the JSON payload within the four documented fields and avoids triggering the filter error.

Verification

  1. Compile and download the project to the Unified Runtime (Panel or PC).
  2. Open WinCC Unified Trace Viewer (Start > Siemens Automation > WinCC Unified > Trace Viewer, or Start > Run > ...<RT path>\Bin\RTILtraceViewer.exe).
  3. Filter on the component GfxJSONFilter and severity Error.
  4. Trigger the pop-up by clicking the configured button. The viewer must not produce a Parse JSON failed entry on this component.
  5. Open the pop-up child faceplate and confirm on the OnLoaded event that this.Properties.UDT, this.Properties.Index, and this.Properties.SecurityNo are populated as expected.
  6. Exit the pop-up, return to the parent, repeat the action 10 times to make sure the trace is clean on every invocation.
Tip: When the optional parameters are passed, the total payload size typically drops below 512 bytes per call. A persistent Parse JSON failed at higher call rates is a useful early indicator of a misuse of the FaceplateType scope. Capture the trace to a file with RTILtraceViewer.exe -f trace.csv -s <rt-name> and archive it for regression tests.

Method Signatures Compared

Aspect UI scope (UI.OpenFaceplateInPopup) FaceplateType scope (Faceplate.OpenFaceplateInPopup)
Documentation source TIA Portal V20 JS reference Same model, Faceplate object in the FaceplateType JS reference
First argument Screen name (String) Faceplate type name (String)
Default for missing optional args Inferred from the screen object Not inferred — undefined in payload
Interface data forwarding Caller supplies an explicit parameters array Inherited automatically from the parent faceplate's Properties
JSON filter behaviour Default object serializes cleanly Truncated payload raises Parse JSON failed
Common error Wrong screen name or wrong parameter array type Missing modal / center arguments

Underlying JSON Filter Mechanics

WinCC Unified uses an OPC UA Pub/Sub-inspired message format between the rendering engine and the property container. Each faceplate container publishes a typed schema; the GfxJSONFilter component is responsible for translating the JavaScript call into a message that matches that schema. When arguments are undefined, the serializer has two options:

  • Inject a schema-valid default — the option the UI scope uses, because the screen object is always available to provide defaults.
  • Emit undefined literally — the option the FaceplateType scope currently takes, because the faceplate container is not a child of the script's this.

Option two produces JSON of the form {"a":"FP_pop_up_empty_V_0_0_2","b":"title","c":,"d":}, which the receiving parser rejects. This is the same kind of error surfaced by JSON.parse in browser JavaScript when it receives malformed text. The Mozilla Developer Network documents the equivalent error in SyntaxError: JSON.parse: bad parsing — MDN; the WinCC runtime uses the same engine to deserialize property updates, so the symptom is the same.

Other Scenarios That Produce "Parse JSON failed"

The error is not unique to the FaceplateType scope. The Trace Viewer filter GfxJSONFilter reports the same string for several distinct issues, all of which should be ruled out before assuming the faceplate-popup cause:

Scenario Symptom Mitigation
Custom web control posting a non-JSON body Same trace, but call site is a web control, not a faceplate Wrap the payload in JSON.stringify(...) before postMessage
Thingworx service input bound to a non-string Service returns Unable To Parse JSON Request Change the service input type to String and use parseInt() in script — the documented workaround in PTC Thingworx community
OPC UA subscription delivering an unexpected type Trace happens during value dispatch, not user interaction Validate subscription types match the HMI tag types
Faceplate instance name containing a colon or slash Trace happens on first Open Restrict instance names to [A-Za-z0-9_]
Broken interface mapping after refactor Trace repeats on every load until the mapping is repaired Use the engineering "Type > Update instances" function after any interface change

Best Practices for Pop-up Faceplates

  1. Always supply all four arguments when calling from a FaceplateType scope. Build a thin wrapper if the call site would otherwise become noisy.
  2. Centralise the wrapper in a script module so the contract is enforced across the project:
// MyFaceplateUtils.js
function openDetailPopup(sType, sTitle, bModal, bCenter) {
  Faceplate.OpenFaceplateInPopup(sType, sTitle, bModal, bCenter);
}
  1. Prefer the inherited Properties over a side-channel tag whenever the data is already on the parent faceplate's interface.
  2. Pre-compute the title before the call so the JSON payload contains a string literal, not a function reference that the filter cannot serialize.
  3. Avoid recursive pop-ups: a faceplate inside a pop-up that calls OpenFaceplateInPopup again on its own type produces a stack of modal windows and complicates the JSON filter because the inheritance chain grows. Use a confirmation pattern via a tag instead.
  4. Keep modal pop-ups short-lived: a modal window blocks the parent screen from refreshing tags, which can cause connection loss alarms if the user walks away.
  5. Test on the target panel before shipping: PC RT masks some errors because the host browser engine is more forgiving of malformed JSON. The Panel runtime is stricter, which is usually where the trace entry shows up first.

Commissioning Checklist

Step Action Pass criterion
1 Inspect every Faceplate.OpenFaceplateInPopup call in the project (cross-reference with the engineering search) All four arguments present
2 Compile and download No build warnings about missing arguments
3 Start Trace Viewer, filter on GfxJSONFilter / Error Empty filter result
4 Open each pop-up 5 times in a row No trace entry, no property loss
5 Verify interface inheritance: UDT, UDT_HMI, Index, SecurityNo Values match the parent faceplate instance
6 Force-close the pop-up via the X button Parent screen does not log Parse JSON failed on dispose
7 Archive the trace as part of the FAT report Trace file included in the project delivery package

Related Methods to Audit

Several adjacent methods share the same four-argument design and trigger the same filter when arguments are dropped. Audit them at the same time:

  • Faceplate.OpenFaceplateInPopup — pop-up window with the four-argument signature described above
  • UI.OpenScreenInPopup — pop-up hosting a full screen, accepts the same optional fields
  • Screen.OpenScreenInPopup — instance-level variant; defaults are inferred from the parent screen object
  • Faceplate.OpenFaceplateInMainWindow — replaces the main window content with a faceplate; default arguments are required for the same reason

All of them route through GfxJSONFilter. Treat the trace entry as a contract violation: the contract is "four typed fields, no undefined values".

FAQ

Why does the pop-up still open even when the trace shows "Parse JSON failed"?

The visual component is constructed before the JSON filter is invoked, so the user sees the pop-up appear. The trace entry is logged on the inheritance roundtrip that follows, after the visual layer has already been drawn. Functionally the pop-up is open, but interface data such as UDT, UDT_HMI, Index, and SecurityNo are not propagated to the child instance.

Are the modal and centre parameters really optional if omitting them breaks the call?

From the documentation perspective they are optional, but the runtime JSON filter in the FaceplateType scope is hard-wired to emit four fields. The "optional" label applies to the UI scope only. In the FaceplateType scope, pass true, false (or whichever values match the design) for every call.

Can I pass a custom data object to the child faceplate?

No. The FaceplateType scope signature accepts only the four documented fields. To forward a custom value, write it to a tag (or to a UDT member on the parent interface) and read it from the child faceplate's OnLoaded event. Wrapping a fifth argument in the call will trigger the same Parse JSON failed error.

Does this affect TIA Portal V17 and V18 projects, or only V20?

The behaviour has been reproducible on every WinCC Unified release that exposes the FaceplateType scope, including V17, V18, V19 and V20. The trace message format is consistent across versions. The customer sample was generated on TIA Portal V20 with build tag SIM_24220041_NEO_V106, but the fix is identical on older versions.

Where can I see the official method documentation?

The TIA Portal V20 cloud documentation for UI.OpenFaceplateInPopup() describes the UI-scope signature and the parameter semantics. For the FaceplateType scope, refer to the same WinCC Unified JavaScript Object Model reference, section "Faceplate". The JSON parse error is documented in the broader web standard at MDN: SyntaxError: JSON.parse: bad parsing.

Back to blog