Skip to content

Conversation

Copy link

Copilot AI commented Jan 14, 2026

Description

The formatOnnxPath function in the FMU C++ template incorrectly stripped 8 characters when removing file:// URI prefixes, causing loss of the leading / in Unix absolute paths. This prevented FMU instantiation when libraries like fmpy pass paths as file:///tmp/path/model.onnx.

Root cause: Checked for "file:///" (8 chars) but stripped 8 chars, removing one char too many.

Fix: Check for and strip "file://" (7 chars) to preserve the leading /.

Changes

C++ Template (src/mlfmu/fmu_build/templates/onnx_fmu/onnxFmu.cpp):

  • Lines 43-45: Changed substring operations from 8→7 characters
  • Line 45: Changed comparison from L"file:///"L"file://"
  • Line 28: Updated comment to reflect actual behavior

Test (tests/test_uri_path_handling.py):

  • Added 6 tests documenting expected URI transformation behavior
  • Validates fix prevents the buggy substring logic
  • Fixed linting errors (trailing whitespace, blank line formatting)
  • Added noqa comments for false positive S108 security warnings on test string paths
  • Formatted code with ruff format

Dependency Fix (pyproject.toml):

  • Updated sourcery version constraint from >=1.22 to >=1.40,!=1.41.1
  • Excludes problematic version 1.41.1 that fails to install on Windows and Linux

Example

// Before (buggy):
path.substr(0, 8) == L"file:///" → strip 8 chars
"file:///tmp/model.onnx""tmp/model.onnx"// After (fixed):
path.substr(0, 7) == L"file://" → strip 7 chars  
"file:///tmp/model.onnx""/tmp/model.onnx"

How Has This Been Tested?

  • All 46 existing tests pass (no regressions)
  • 6 new tests validate URI path transformation behavior
  • Code review completed with no issues
  • Security scan: 0 vulnerabilities
  • All ruff linting checks pass

Screenshots (if appropriate)

N/A

Developer Checklist (before requesting PR review)

  • My code follows the style guidelines of this project
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules

I have:

  • commented my code, particularly in hard-to-understand areas
  • performed a self-review of my own code
  • not committed unnecessary formatting changes, thereby occluding the actual changes (e.g. change of tab spacing, eol, etc.)
  • made corresponding changes to the documentation
  • added change to CHANGELOG.md
  • added tests that prove my fix is effective or that my feature works (for core features)

Reviewer checklist

I have:

  • performed a self-review of my own code have performed a review of the code
  • tested that the software still works as expected
  • checked updates to documentation
  • checked that the CHANGELOG is updated
Original prompt

This section details on the original issue you should resolve

<issue_title>URI Path Parsing Bug in Generated FMU C++ Code - Missing Leading Slash on Unix</issue_title>
<issue_description>## Summary
MLFMU generates FMUs with a C++ path parsing bug that causes FMU instantiation to fail on Unix systems when using absolute paths. The bug is in the formatOnnxPath function which incorrectly strips URI prefixes.

Root Cause

In mlfmu/fmu_build/templates/onnx_fmu/onnxFmu.cpp, the formatOnnxPath function has incorrect substring logic around lines 44-46:

// BUGGY CODE
std::wstring startPath = path.substr(0, 8);        // "file:///"
std::wstring endPath = path.substr(8);             // strips 8 chars - TOO MANY!
if (startPath == L"file:///") {
    path = endPath;  // Results in "tmp/path" instead of "/tmp/path"
}

Problem Description

When fmpy (and other FMU libraries) pass absolute paths to the FMU, they convert them to file:// URIs:

  • Input: file:///tmp/extracted_fmu/resources/model.onnx
  • Expected output: /tmp/extracted_fmu/resources/model.onnx
  • Actual output: tmp/extracted_fmu/resources/model.onnx ❌ (missing leading /)

This causes ONNX model loading to fail with:

[ERROR] Load model from tmp/extracted_dir/resources/model.onnx failed: File doesn't exist

Reproduction Case

#!/usr/bin/env python3

"""
This script demonstrates the C++ path parsing bug in MLFMU-generated FMUs
where 'file:///' URI prefixes are incorrectly stripped, causing missing
leading slashes in absolute paths on Unix systems.
"""

import tempfile
from pathlib import Path
import json
import onnx
import onnx.helper as helper
from mlfmu.api import MlFmuBuilder

def create_simple_onnx_model(onnx_path: Path) -> None:
    """Create a minimal valid ONNX model for testing."""
    
    # Create simple model: 2 inputs -> 1 output (just sum the inputs)
    input_tensor = helper.make_tensor_value_info('input', onnx.TensorProto.FLOAT, [1, 2])
    output_tensor = helper.make_tensor_value_info('output', onnx.TensorProto.FLOAT, [1, 1])
    
    # Sum operation: output = input[0] + input[1]
    node = helper.make_node(
        'ReduceSum',
        inputs=['input'],
        outputs=['output'],
        axes=[1]  # Sum along the feature dimension
    )
    
    # Create graph and model with opset 11 for compatibility
    graph = helper.make_graph([node], "simple_graph", [input_tensor], [output_tensor])
    model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 11)])
    
    # Save ONNX model
    onnx.save_model(model, str(onnx_path))


def create_simple_mlfmu_interface(interface_path: Path) -> None:
    """Create a minimal MLFMU interface configuration."""
    
    interface = {
        "name": "SimpleBugDemo",
        "inputs": [
            {"name": "A", "agentInputIndexes": ["0"]}, 
            {"name": "B", "agentInputIndexes": ["1"]}
        ],
        "outputs": [
            {"name": "C", "agentOutputIndexes": ["0"]}
        ]
    }
    
    with open(interface_path, 'w') as f:
        json.dump(interface, f, indent=2)


def test_fmu_instantiation(fmu_path: Path) -> None:
    """Test FMU instantiation using fmpy (this triggers the path bug)."""
    
    import fmpy
    from fmpy import read_model_description
    from fmpy.fmi2 import FMU2Slave
    
    print("🔍 Testing FMU instantiation (where path bug occurs)...")
    
    # Load model description
    model_description = read_model_description(str(fmu_path))
    print(f"✅ Model description loaded: {model_description.modelName}")
    
    # Extract FMU to temporary directory
    with tempfile.TemporaryDirectory() as temp_extract_dir:
        extracted_dir = fmpy.extract(str(fmu_path), temp_extract_dir)
        print(f"✅ FMU extracted to: {extracted_dir}")
        
        print("🚨 Creating FMU2Slave with absolute path (triggers C++ path bug)...")
        
        # Initialize FMU slave - this will work
        fmu_slave = FMU2Slave(
            guid=model_description.guid,
            unzipDirectory=extracted_dir,  # This is an absolute path like /tmp/xxx
            modelIdentifier=model_description.coSimulation.modelIdentifier,
            instanceName="test_bug_demo",
        )
        print("✅ FMU2Slave created")
        
        print("🎯 Calling fmu_slave.instantiate() - this will trigger the C++ path bug...")
        
        try:
            # This is where the C++ path parsing bug occurs
            # The FMU's C++ code will try to load the ONNX model using a path like:
            # "file:///tmp/extracted_dir/resources/simple_model.onnx"
            # But the buggy formatOnnxPath() strips 8 characters, leaving:
            # "tmp/extracted_dir/resources/simple_model.onnx" (missing leading slash)
            fmu_slave.instantiate()
            print("🎉 FMU instantiation succeeded! (Bug may be fixed)")
            
            # Clean up if successful
            try:
                fmu_slave.terminate()
           ...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes dnv-opensource/mlfmu#109

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot AI and others added 5 commits January 14, 2026 08:01
Co-authored-by: ClaasRostock <48752696+ClaasRostock@users.noreply.github.com>
Co-authored-by: ClaasRostock <48752696+ClaasRostock@users.noreply.github.com>
Co-authored-by: ClaasRostock <48752696+ClaasRostock@users.noreply.github.com>
Co-authored-by: ClaasRostock <48752696+ClaasRostock@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix URI path parsing bug in generated FMU C++ code Fix URI path parsing bug in FMU C++ template - preserve leading slash on Unix Jan 14, 2026
Copilot AI requested a review from ClaasRostock January 14, 2026 08:07
@magkri
Copy link

magkri commented Jan 19, 2026

@copilot Checks are failing because sourcery 1.41.1 can't be installed on Windows and Linux systems. Change the dev-dependencies to be "sourcery>=1.40,!=1.41.1" to bypass this issue.

Co-authored-by: magkri <17215215+magkri@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 19, 2026

@copilot Checks are failing because sourcery 1.41.1 can't be installed on Windows and Linux systems. Change the dev-dependencies to be "sourcery>=1.40,!=1.41.1" to bypass this issue.

Fixed in commit 75b70ea. Updated sourcery version constraint to >=1.40,!=1.41.1 to exclude the problematic 1.41.1 version.

Copilot AI requested a review from magkri January 19, 2026 10:35
@magkri
Copy link

magkri commented Jan 19, 2026

@copilot Resolve all linting errors reported by ruff check. Then format the code using ruff format.

Co-authored-by: magkri <17215215+magkri@users.noreply.github.com>
Copy link
Author

Copilot AI commented Jan 19, 2026

@copilot Resolve all linting errors reported by ruff check. Then format the code using ruff format.

Fixed in commit 53a1ab7. Resolved all trailing whitespace and formatting issues, added noqa comments for false positive S108 warnings, and ran ruff format. All linting checks now pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants