Skip to content

Error Handling

Dietmar Borgards edited this page Feb 28, 2026 · 2 revisions

Error Handling

EdsDcfNet uses exceptions as its primary error mechanism and is designed to be tolerant of minor deviations in real-world EDS/DCF files.


Exception Types

EdsParseException

Thrown when a parse error is encountered while reading an EDS, DCF, or CPJ file.

using EdsDcfNet.Exceptions;

try
{
    var eds = CanOpenFile.ReadEds("device.eds");
}
catch (EdsParseException ex)
{
    Console.WriteLine($"Message:  {ex.Message}");
    Console.WriteLine($"Section:  {ex.SectionName}"); // e.g. "[DeviceInfo]"
    Console.WriteLine($"Line:     {ex.LineNumber}");   // null if not applicable
}
Property Type Description
Message string Human-readable error description
SectionName string? INI section where the error occurred
LineNumber int? Line number in the file (when available)

When thrown:

  • A mandatory section (e.g., [DeviceInfo]) is missing
  • A required field within a section cannot be parsed
  • A $NODEID formula results in overflow or underflow
  • A value is in an unexpected format that cannot be converted

DcfWriteException

Thrown when an error occurs during DCF serialization.

try
{
    CanOpenFile.WriteDcf(dcf, "output.dcf");
}
catch (DcfWriteException ex)
{
    Console.WriteLine($"Write error: {ex.Message}");
    Console.WriteLine($"Section:     {ex.SectionName}");
}
Property Type Description
Message string Human-readable error description
SectionName string? Section being written when the error occurred

EdsWriteException

Thrown when an error occurs during EDS serialization.

try
{
    CanOpenFile.WriteEds(eds, "output.eds");
}
catch (EdsWriteException ex)
{
    Console.WriteLine($"Write error: {ex.Message}");
    Console.WriteLine($"Section:     {ex.SectionName}");
}
Property Type Description
Message string Human-readable error description
SectionName string? Section being written when the error occurred

ArgumentException (Standard .NET)

Thrown for invalid input parameters validated at the API boundary:

// NodeId must be 1–127
try
{
    var dcf = CanOpenFile.EdsToDcf(eds, nodeId: 0, baudrate: 250);
}
catch (ArgumentException ex)
{
    Console.WriteLine(ex.Message); // "NodeId must be between 1 and 127"
}

Error Tolerance Strategy

EdsDcfNet is intentionally tolerant of imperfect real-world files:

Mandatory vs. Optional Sections

Read EDS/DCF
│
├── Required section missing?  → EdsParseException
│
└── Optional section missing?  → null / default value (no exception)
    │
    └── Value parseable?
        ├── Yes → stored in model
        └── No  → EdsParseException with context

AccessType Fallback

If an AccessType value is unknown or invalid, the library falls back to ReadOnly instead of throwing:

AccessType = "rw"     → ReadWrite     ✓ normal
AccessType = "ro"     → ReadOnly      ✓ normal
AccessType = "xyz"    → ReadOnly      ✓ tolerant fallback (no exception)

This is a deliberate trade-off to maximize interoperability with non-compliant manufacturer EDS files.

Unknown Sections

Unknown or vendor-specific sections are never rejected. They are stored in AdditionalSections and written back unchanged:

var eds = CanOpenFile.ReadEds("vendor_device.eds");
// Vendor-specific [VendorTool] section is in eds.AdditionalSections
// No warning, no exception

Missing [DeviceCommissioning] Section

If a DCF file omits the entire [DeviceCommissioning] section (no NodeID key at all), parsing succeeds and DeviceCommissioning.NodeId defaults to 0 — no exception is thrown. If a NodeID key is present but outside the valid range 1–127, an EdsParseException is thrown.


Comprehensive Error Handling Example

using EdsDcfNet;
using EdsDcfNet.Exceptions;

public static DeviceConfigurationFile? SafeLoadDcf(string path)
{
    try
    {
        return CanOpenFile.ReadDcf(path);
    }
    catch (EdsParseException ex)
    {
        Console.Error.WriteLine($"[ERROR] Failed to parse '{path}'");
        Console.Error.WriteLine($"  {ex.Message}");
        if (ex.SectionName != null)
            Console.Error.WriteLine($"  Section: {ex.SectionName}");
        if (ex.LineNumber.HasValue)
            Console.Error.WriteLine($"  Line: {ex.LineNumber}");
        return null;
    }
    catch (FileNotFoundException)
    {
        Console.Error.WriteLine($"[ERROR] File not found: {path}");
        return null;
    }
    catch (UnauthorizedAccessException)
    {
        Console.Error.WriteLine($"[ERROR] No permission to read: {path}");
        return null;
    }
}

public static bool SafeWriteDcf(DeviceConfigurationFile dcf, string path)
{
    try
    {
        CanOpenFile.WriteDcf(dcf, path);
        return true;
    }
    catch (DcfWriteException ex)
    {
        Console.Error.WriteLine($"[ERROR] Failed to write DCF: {ex.Message}");
        return false;
    }
    catch (IOException ex)
    {
        Console.Error.WriteLine($"[ERROR] IO error writing '{path}': {ex.Message}");
        return false;
    }
}

public static bool SafeWriteEds(ElectronicDataSheet eds, string path)
{
    try
    {
        CanOpenFile.WriteEds(eds, path);
        return true;
    }
    catch (EdsWriteException ex)
    {
        Console.Error.WriteLine($"[ERROR] Failed to write EDS: {ex.Message}");
        return false;
    }
    catch (IOException ex)
    {
        Console.Error.WriteLine($"[ERROR] IO error writing '{path}': {ex.Message}");
        return false;
    }
}

Diagnosing Parse Errors

When EdsParseException is thrown, use the additional properties for diagnostics:

catch (EdsParseException ex)
{
    // Build a diagnostic message
    var sb = new System.Text.StringBuilder();
    sb.Append("EDS parse error");
    if (ex.SectionName != null)
        sb.Append($" in section [{ex.SectionName}]");
    if (ex.LineNumber.HasValue)
        sb.Append($" at line {ex.LineNumber}");
    sb.Append($": {ex.Message}");

    Console.Error.WriteLine(sb.ToString());
    // Example: "EDS parse error in section [DeviceInfo] at line 42: Invalid VendorNumber format"
}

Testing without Files

Use the *FromString methods to test error handling without files on disk:

// Test that a malformed EDS throws correctly
string brokenEds = "[FileInfo]\nFileName=test.eds\n"; // missing [DeviceInfo]

try
{
    var eds = CanOpenFile.ReadEdsFromString(brokenEds);
    // Should not reach here
}
catch (EdsParseException ex)
{
    Assert.Contains("DeviceInfo", ex.Message);
}

See Also

Clone this wiki locally