iflytek/astron-agent · warning
Parse generated skill metadata failed
Error message
Parse generated skill metadata failed
What it means
parseGeneratedMetadata takes the LLM's free-text response and extracts a valid skill name and description (with length clamping). If the content is null, unparseable, or the name fails isValidSkillName, the catch logs this warning (no workflow ID here) and returns null, causing the caller to use fallback metadata.
Solutions
- Tighten buildMetadataPrompt to demand strict output format and add an example, improving parse success rate
- Make parseGeneratedMetadata tolerant: strip markdown fences, trim, and accept more name characters in isValidSkillName
- Log the raw model content (truncated) at debug level to diagnose recurring parse failures
- If name validation rejects, sanitize (strip illegal chars, truncate) instead of discarding entirely
Example fix
// before
return new SkillMetadata(name, description, true);
} catch (Exception e) {
log.warn("Parse generated skill metadata failed");
return null;
}
// after
} catch (Exception e) {
log.warn("Parse generated skill metadata failed, rawContent={}", StringUtils.abbreviate(raw, 200), e);
return sanitizeOrFallback(raw);
} Defensive patterns
Strategy: fallback
Validate before calling
// pre-validate model output shape before detailed parsing
if (content == null || content.isBlank()) return null;
if (!content.contains("name") && !content.contains("description")) return null; Type guard
SkillMetadata tryParse(String raw) {
if (raw == null || raw.isBlank()) return null;
String cleaned = raw.replaceAll("^```.*?\\n|```$", "").trim();
return parseGeneratedMetadata(cleaned);
} Try / catch
SkillMetadata meta = parseGeneratedMetadata(content);
if (meta == null) {
log.warn("Parse generated skill metadata failed, falling back for workflowId={}", workflowId);
meta = fallback;
} Prevention
- Instruct the model with a strict JSON output schema and provide an example in the prompt
- Sanitize raw output: strip markdown fences, whitespace, and preamble before parsing
- Loosen isValidSkillName (trim, allow common characters) so valid names are not discarded
- Log truncated raw responses at debug level to diagnose recurring parse failures
When it happens
Trigger: generated LLM content does not match the expected format the parser expects — empty content after timeout/exception, model returning prose instead of the requested structured name/description, or name failing isValidSkillName (blank, invalid characters, too long).
Common situations: Model ignoring output-format instructions; responses in another language or wrapped in markdown the parser can't strip; overly long generated names rejected by validation; LLM returning refusal/error text instead of metadata.
Related errors
- Generate workflow skill metadata failed, workflowId=
- -40008
- OPEN_AI_API_ERROR
- Unable to parse boolean value: '
- RESPONSE_FAILED
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/d7c976bd50f062ca.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/service/workflow/impl/WorkflowSkillExportServiceImpl.java:182
int start = content.indexOf('{');
int end = content.lastIndexOf('}');
if (start < 0 || end <= start) {
return null;
}
try {
JSONObject json = JSON.parseObject(content.substring(start, end + 1));
String name = StringUtils.trim(json.getString("name"));
String description = StringUtils.trim(json.getString("description"));
if (!isValidSkillName(name) || StringUtils.isBlank(description)) {
return null;
}
if (description.length() > SKILL_DESCRIPTION_MAX_LENGTH) {
description = description.substring(0, SKILL_DESCRIPTION_MAX_LENGTH);
}
return new SkillMetadata(name, description, true);
} catch (Exception e) {
log.warn("Parse generated skill metadata failed");
return null;
}
}
private boolean isValidSkillName(String name) {
return StringUtils.isNotBlank(name)
&& name.length() <= SKILL_NAME_MAX_LENGTH
&& name.matches("[a-z0-9][a-z0-9-]*");
}
private String toSkillName(String workflowName, Long workflowId) {
String normalizedText = Normalizer.normalize(
StringUtils.defaultString(workflowName),
Normalizer.Form.NFKD);
StringBuilder normalizedBuilder = new StringBuilder(normalizedText.length());
boolean previousHyphen = false;
for (int i = 0; i < normalizedText.length(); i++) {
char current = normalizedText.charAt(i);View on GitHub (pinned to 5e758547a8)