{"record":{"id":"f0f9f655be8756bd","repo":"phar-io/manifest","slug":"attribute-s-not-set-on-element-s","errorCode":null,"errorMessage":"Attribute %s not set on element %s","messagePattern":"Attribute (.+?) not set on element (.+?)","errorType":"exception","errorClass":"ManifestElementException","httpStatus":null,"severity":"error","filePath":"src/xml/ManifestElement.php","lineNumber":29,"sourceCode":"namespace PharIo\\Manifest;\n\nuse DOMElement;\nuse DOMNodeList;\nuse function sprintf;\n\nclass ManifestElement {\n    public const XMLNS = 'https://phar.io/xml/manifest/1.0';\n\n    /** @var DOMElement */\n    private $element;\n\n    public function __construct(DOMElement $element) {\n        $this->element = $element;\n    }\n\n    protected function getAttributeValue(string $name): string {\n        if (!$this->element->hasAttribute($name)) {\n            throw new ManifestElementException(\n                sprintf(\n                    'Attribute %s not set on element %s',\n                    $name,\n                    $this->element->localName\n                )\n            );\n        }\n\n        return $this->element->getAttribute($name);\n    }\n\n    protected function hasAttribute(string $name): bool {\n        return $this->element->hasAttribute($name);\n    }\n\n    protected function getChildByName(string $elementName): DOMElement {\n        $element = $this->element->getElementsByTagNameNS(self::XMLNS, $elementName)->item(0);\n","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/phar-io/manifest/blob/c581d4941e196459bf76c945a8ca922963a66708/src/xml/ManifestElement.php#L11-L47","documentation":"ManifestElement::getAttributeValue is the base accessor for all manifest attribute getters (getName, getEmail, getVersion, getType, getFor, getCompatible). When the wrapped DOMElement lacks the requested attribute it throws ManifestElementException('Attribute %s not set on element %s'), naming the attribute and the element's localName.","triggerScenarios":"Calling any attribute getter (getName, getEmail, getVersion, getType, getFor, getCompatible) on a manifest element that does not carry the corresponding attribute — e.g. reading ->getAuthorElement()->getEmail() when the <author> element has no email attribute.","commonSituations":"Hand-edited manifests with omitted optional-looking but required attributes; older manifests generated before an attribute became mandatory; author/vendor elements written without email or url.","solutions":["Add the missing attribute named in the message to the element in the manifest XML","Wrap the getter call in try-catch for ManifestElementException","Regenerate the manifest with the current tool version","Validate the manifest against the phar.io XSD before consuming it"],"exampleFix":"// before\n<author>Sebastian</author>\n// after\n<author name=\"Sebastian\" email=\"dev@example.com\"/>","handlingStrategy":"type-guard","validationCode":"if (!$authorEl->hasAttribute('email')) { throw new RuntimeException('Author element has no email attribute'); }","typeGuard":"function attributeOrNull(DOMElement $el, string $name): ?string { return $el->hasAttribute($name) ? $el->getAttribute($name) : null; }","tryCatchPattern":"try { $email = $author->getEmail(); } catch (ManifestElementException $e) { $email = null; log_warning($e->getMessage()); }","preventionTips":["Check DOMElement::hasAttribute() before calling attribute getters","Require complete manifests from your build pipeline","Validate the manifest against the phar.io XSD to enforce mandatory attributes"],"tags":["xml","manifest","missing-attribute"],"backgroundTag":"schema-validation-failed","analyzedSha":"c581d4941e196459bf76c945a8ca922963a66708","analyzedAt":"2026-09-14T11:08:47.165Z","contentChangedAt":"2026-09-14T11:08:47.165Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}