{"record":{"id":"a11a9ce8caaf6902","repo":"shwenzhang/AndResGuard","slug":"invalid-config-file-missing-required-attribute-s","errorCode":null,"errorMessage":"Invalid config file: Missing required attribute %s\n","messagePattern":"Invalid config file: Missing required attribute (.+?)\n","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/com/tencent/mm/resourceproguard/Configuration.java","lineNumber":320,"sourceCode":"  }\n\n  private void readSignFromXml(Node node, File xmlConfigFileParentFile) throws IOException {\n    if (mSignatureFile != null) {\n      System.err.println(\"already set the sign info from command line, ignore this\");\n      return;\n    }\n\n    NodeList childNodes = node.getChildNodes();\n\n    if (childNodes.getLength() > 0) {\n      for (int j = 0, n = childNodes.getLength(); j < n; j++) {\n        Node child = childNodes.item(j);\n        if (child.getNodeType() == Node.ELEMENT_NODE) {\n          Element check = (Element) child;\n          String tagName = check.getTagName();\n          String vaule = check.getAttribute(ATTR_VALUE);\n          if (vaule.length() == 0) {\n            throw new IOException(String.format(\"Invalid config file: Missing required attribute %s\\n\", ATTR_VALUE));\n          }\n\n          switch (tagName) {\n            case ATTR_SIGNFILE_PATH:\n              char ch = vaule.charAt(0);\n              switch (ch) {\n                // supports the writting style like ~/.android/debug.keystore. the symbol ~ represent the home directory of the current user.\n                case '~':\n                  mSignatureFile = new File(String.format(\"%s%s\", System.getProperty(\"user.home\"), vaule.substring(1)));\n                  break;\n                // relative to the directory of the xml config file.\n                case '.':\n                  mSignatureFile = new File(xmlConfigFileParentFile, vaule);\n                  break;\n                // keep the origin logical.\n                default:\n                  mSignatureFile = new File(vaule);\n              }","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/com/tencent/mm/resourceproguard/Configuration.java#L302-L338","documentation":"readSignFromXml throws this IOException when a child element inside the <sign> section of the config XML has an empty or missing 'value' attribute. Every child of <sign> (path, keypass, storepass, alias) must carry a non-empty value because signing cannot proceed without them. The check runs before the tagName switch, so it applies to all sign sub-elements.","triggerScenarios":"Config XML like <issue id=\"sign\"><path value=\"\"/></issue> or a child tag without a value attribute; readSignFromXml reads check.getAttribute(\"value\"), finds length 0, and throws.","commonSituations":"Leaving the signing keypass or storepass value blank to avoid committing a password, then running the build; template sign sections with placeholder empty values; generated configs where the signing block was never populated.","solutions":["Fill in the value attribute for every child of <sign>: path, keypass, storepass, alias","Pass the signing config via command-line arguments (--signatureFile, --keypass, etc.) instead of XML if you want to keep secrets out of the file","Remove the <sign> issue entirely if you do not want to re-sign, letting the original signature be kept via useSignAPK=false"],"exampleFix":"// before (config.xml)\n<issue id=\"sign\">\n  <path value=\"\"/>\n</issue>\n// after (config.xml)\n<issue id=\"sign\">\n  <path value=\"../signing/release.keystore\"/>\n  <storepass value=\"changeit\"/>\n  <keypass value=\"changeit\"/>\n  <alias value=\"release\"/>\n</issue>","handlingStrategy":"validation","validationCode":"NodeList sign = doc.getElementsByTagName(\"sign\");\nif (sign.getLength() > 0) {\n  NodeList children = ((Element) sign.item(0)).getChildNodes();\n  for (int i = 0; i < children.getLength(); i++) {\n    Node n = children.item(i);\n    if (n.getNodeType() == Node.ELEMENT_NODE && ((Element) n).getAttribute(\"value\").isEmpty()) {\n      throw new IllegalStateException(\"<sign> child \" + n.getNodeName() + \" has empty value\");\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  new Configuration(configFile, ...);\n} catch (IOException e) {\n  if (e.getMessage().contains(\"Missing required attribute value\") && e.getStackTrace()[0].getMethodName().equals(\"readSignFromXml\")) {\n    // prompt for signing credentials or route them via CLI args\n  }\n  throw e;\n}","preventionTips":["Provide signing values via command-line options instead of leaving XML attributes empty","Fill path, keypass, storepass, and alias together whenever you add a <sign> issue","Validate the whole sign section in CI before invoking resourceproguard"],"tags":["android","config","xml","signing"],"backgroundTag":"missing-required-config-field","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}