Help Understanding Parser Logic

Hey everyone,

I've started working on a custom parser for NetSuite, since it's a major product my company currently uses. Initially, I was having some success extracting the necessary data from my logs. However, when I switched to a different raw log, I began running into issues.

I initialized all the variables I could identify from the raw logs, assuming that if a field didnโ€™t exist, the parser would simply skip it and continue processing the rest. Unfortunately, that doesnโ€™t seem to be happening.

Right now, Iโ€™m just dumping these fields into the additional_fields section. I know thatโ€™s not best practice, but since Iโ€™m the only one using the SIEM at the moment and enrichment for this log type isnโ€™t a high priority, itโ€™s working for now.

Here is my current parser logic (I removed some to make this post shorter):

filter {
  # This parser is just working for the incident we are currently having with GSM - it will need to be changed to include other fields
  mutate {
    replace => {
      "udm_event.idm.read_only_udm.metadata.vendor_name" => "Net Suite"
      "udm_event.idm.read_only_udm.metadata.event_type" => "GENERIC_EVENT"

      "title" => ""
      "type" => ""
      "user" => ""
      "scripttype" => ""
      "detail.clientReferenceInformation.code" => ""
      "detail.clientReferenceInformation.partner.solutionId" => ""
      #"detail.processingInformation.authorizationOptions.initiator.credentialStoredOnFile" => ""
      #"detail.processingInformation.authorizationOptions.ignoreAvsResult" => ""
      #"detail.processingInformation.authorizationOptions.ignoreCvResult" => ""
      "detail.processingInformation.commerceIndicator" => ""
      "detail.paymentInformation.card.number" => ""
      "detail.paymentInformation.card.expirationMonth" => ""
      "detail.paymentInformation.card.expirationYear" => ""
      "detail.paymentInformation.card.securityCode" => ""
      "detail.paymentInformation.card.type" => ""
      "detail.orderInformation.amountDetails.totalAmount" => ""
      "detail.orderInformation.amountDetails.currency" => ""
      "detail.orderInformation.amountDetails.discountAmount" => ""
      "detail.orderInformation.amountDetails.taxAmount" => ""
      "detail.orderInformation.billTo.firstName" => ""
      "detail.orderInformation.billTo.lastName" => ""
      "detail.orderInformation.billTo.address1" => ""
      "detail.orderInformation.billTo.locality" => ""
      "detail.orderInformation.billTo.administrativeArea" => ""
      "detail.orderInformation.billTo.postalCode" => ""
      "detail.orderInformation.billTo.country" => ""
      "detail.orderInformation.billTo.email" => ""
      "detail.orderInformation.billTo.phoneNumber" => ""
      "detail.orderInformation.shipTo.firstName" => ""
      "detail.orderInformation.shipTo.lastName" => ""
      "detail.orderInformation.shipTo.address1" => ""
      "detail.orderInformation.shipTo.locality" => ""
      "detail.orderInformation.shipTo.administrativeArea" => ""
      "detail.orderInformation.shipTo.postalCode" => ""
      "detail.orderInformation.shipTo.country" => ""
      "detail.paymentInsightsInformation.responseInsights.category" => ""
    }
  }

  # Parse JSON
  json {
    source => "message"
    on_error => "not_json"
  }

  statedump{label=TheStart}

  # Handle the title field
  if [title] != "" {
    mutate {
      replace => {
        "title_field.key" => "Title"
        "title_field.value.string_value" => "%{title}"
      }
    }
    mutate {
      merge => {
        "udm_event.idm.read_only_udm.additional.fields" => "title_field"
      }
    }
  }

  # Handle the type field
  if [type] != "" {
    mutate {
      replace => {
        "type_field.key" => "Type"
        "type_field.value.string_value" => "%{type}"
      }
    }
    mutate {
      merge => {
        "udm_event.idm.read_only_udm.additional.fields" => "type_field"
      }
    }
  }

  # Handle the user field
  if [user] != "" {
    mutate {
      replace => {
        "user_field.key" => "User"
        "user_field.value.string_value" => "%{user}"
      }
    }
    mutate {
      merge => {
        "udm_event.idm.read_only_udm.additional.fields" => "user_field"
      }
    }
  }

  # Handle the scripttype field
  if [scripttype] != "" {
    mutate {
      replace => {
        "scripttype_field.key" => "ScriptType"
        "scripttype_field.value.string_value" => "%{scripttype}"
      }
    }
    mutate {
      merge => {
        "udm_event.idm.read_only_udm.additional.fields" => "scripttype_field"
      }
    }
  }

  # Handle client reference information code
  if [detail][clientReferenceInformation][code] != "" {
    mutate {
        replace => {
            "clientrefcode_field.key" => "ClientReferenceCode"
            "clientrefcode_field.value.string_value" => "%{detail.clientReferenceInformation.code}"
        }
    }
    mutate {
        merge => {
            "udm_event.idm.read_only_udm.additional.fields" => "clientrefcode_field"
        }
    }
  }

  # Handle client solution ID
  if [detail][clientReferenceInformation][partner][solutionId] != "" {
    mutate {
        replace => {
            "solutionid_field.key" => "ClientSolutionId"
            "solutionid_field.value.string_value" => "%{detail.clientReferenceInformation.partner.solutionId}"
        }
    }
    mutate {
        merge => {
            "udm_event.idm.read_only_udm.additional.fields" => "solutionid_field"
        }
    }
  }

  statedump{label=TheEnd}

  mutate {
    merge => {
      "@output" => "udm_event"
    }
  }

This is the error that I am running into currently:
generic::unknown: pipeline.ParseLogEntry failed: LOG_PARSING_CBN_ERROR: "generic::invalid_argument: pipeline failed: filter conditional (2) failed: failed to evaluate expression: generic::invalid_argument: \"detail.clientReferenceInformation\" not found in state data"

And here is the raw log from Netsuite that I am attempting to parse:
{
"title": " Basic AUTHORIZATION Response Code",
"type": "Audit",
"date": "6/17/2025",
"time": "11:00 pm",
"user": "889990397 USERNAME",
"scripttype": "Payment Processing Plug-in",
"detail": 201,
"name.script": "Cybersource for NetSuite"
}

1 9 230
9 REPLIES 9