Summary
parseActivationResult reports Success: true even when SAP returns E-type activation errors. parseSyntaxCheckResults may also silently drop error messages. Root cause: Go's encoding/xml does not match namespace-qualified attributes (adtcomp:type="E") against unqualified struct tags (xml:"type,attr").
Root cause
SAP ADT activation responses use namespace-prefixed attributes:
<adtcomp:activationLog xmlns:adtcomp="http://www.sap.com/adt/activation">
<adtcomp:messages>
<adtcomp:msg adtcomp:type="E" adtcomp:objDescr="ZTEST" adtcomp:line="5">
<adtcomp:shortText><adtcomp:txt>Syntax error</adtcomp:txt></adtcomp:shortText>
</adtcomp:msg>
</adtcomp:messages>
</adtcomp:activationLog>
Go's xml.Unmarshal matches element names by local name regardless of namespace prefix (so <adtcomp:msg> is found by xml:"msg"), but attribute matching is strict: xml:"type,attr" will NOT match adtcomp:type="E". Result: msg.Type is always "", strings.ContainsAny("", "EAX") is false, and Success stays true.
parseSyntaxCheckResults has a partial workaround (strings.ReplaceAll(xmlStr, "chkrun:", "")) but it turns xmlns:chkrun="..." into a default namespace declaration xmlns="...", which can cause Go's parser to miss elements in that namespace.
Impact
- Activation errors (syntax errors, ATC findings blocking activation) are silently swallowed — vsp reports success even when SAP refused to activate the object
- Syntax check results may be missed depending on SAP version / namespace declaration style
- Affects all object types, but most visible when activating INCL objects where SAP returns error messages without
inactiveObjects (the fallback check)
Fix
Add a stripXMLNamespaces() helper that removes all namespace declarations and all prefix: prefixes before unmarshaling. Apply to both parsers.
var (
reXMLNSDecl = regexp.MustCompile(`\s*xmlns(?::\w+)?="[^"]*"`)
reXMLNSPrefix = regexp.MustCompile(`(</?|\s)(\w[\w-]*):([\w])`)
)
func stripXMLNamespaces(data []byte) []byte {
s := reXMLNSDecl.ReplaceAllString(string(data), "")
s = reXMLNSPrefix.ReplaceAllString(s, "${1}${3}")
return []byte(s)
}
We have this fix running on-prem S/4HANA in our fork (txape10/vibing-steampunk, commit dedfebc) with 6 unit tests covering both parsers and both failure modes (with and without inactiveObjects).
Summary
parseActivationResultreportsSuccess: trueeven when SAP returns E-type activation errors.parseSyntaxCheckResultsmay also silently drop error messages. Root cause: Go'sencoding/xmldoes not match namespace-qualified attributes (adtcomp:type="E") against unqualified struct tags (xml:"type,attr").Root cause
SAP ADT activation responses use namespace-prefixed attributes:
Go's
xml.Unmarshalmatches element names by local name regardless of namespace prefix (so<adtcomp:msg>is found byxml:"msg"), but attribute matching is strict:xml:"type,attr"will NOT matchadtcomp:type="E". Result:msg.Typeis always"",strings.ContainsAny("", "EAX")isfalse, andSuccessstaystrue.parseSyntaxCheckResultshas a partial workaround (strings.ReplaceAll(xmlStr, "chkrun:", "")) but it turnsxmlns:chkrun="..."into a default namespace declarationxmlns="...", which can cause Go's parser to miss elements in that namespace.Impact
inactiveObjects(the fallback check)Fix
Add a
stripXMLNamespaces()helper that removes all namespace declarations and allprefix:prefixes before unmarshaling. Apply to both parsers.We have this fix running on-prem S/4HANA in our fork (
txape10/vibing-steampunk, commitdedfebc) with 6 unit tests covering both parsers and both failure modes (with and withoutinactiveObjects).