floci-io/floci · error · VtlErrorSignal
{errorType}
{errorType}
Error message
{message} What it means
Implements $util.error(message, errorType) from AppSync VTL: aborts the resolver and reports the message with the caller-supplied errorType (e.g. 'Unauthorized', 'Conflict'). The emulator throws VtlErrorSignal carrying both fields; the GraphQL data-plane turns it into an error entry with errorType metadata.
Source
Thrown at src/main/java/io/github/hectorvent/floci/services/appsync/graphql/util/AppSyncUtil.java:209
if (value == null) return "Null";
if (value instanceof String) return "String";
if (value instanceof Boolean) return "Boolean";
if (value instanceof Number) return "Number";
if (value instanceof List<?>) return "List";
if (value instanceof Map<?, ?>) return "Map";
return "Object";
}
public String authType() {
return authTypeValue;
}
public void error(String message) {
throw new VtlErrorSignal(message, "Unknown", null, null);
}
public void error(String message, String errorType) {
throw new VtlErrorSignal(message, errorType, null, null);
}
public void error(String message, String errorType, Object data) {
throw new VtlErrorSignal(message, errorType, data, null);
}
public void error(String message, String errorType, Object data, Object errorInfo) {
throw new VtlErrorSignal(message, errorType, data, errorInfo);
}
public void appendError(String message) {
appendErrorInternal(message, "Unknown", null, null);
}
public void appendError(String message, String errorType) {
appendErrorInternal(message, errorType, null, null);
}
View on GitHub (pinned to 62ff490619)
Solutions
- Check errors[0].errorType (or extensions) in the GraphQL response to find the originating template call.
- If the type is unexpected, fix the condition guarding the $util.error call rather than the message.
- Keep errorType strings aligned with AWS conventions (e.g. 'DynamoDB:ConditionalCheckFailedException') so SDK/AppSync tooling recognizes them.
- For recoverable cases, use $util.appendError instead so the resolver continues and returns data.
Example fix
## before
$util.error("write failed", "RandomError")
## after
$util.error("write failed", "DynamoDB:ConditionalCheckFailedException") Defensive patterns
Strategy: try-catch
Try / catch
try {
return evaluateTemplate(reqMapping, ctx);
} catch (VtlErrorSignal e) {
if ("Unauthorized".equals(e.getErrorType())) throw new UnauthorizedException(e);
throw new TypedGraphQLError(e.getMessage(), e.getErrorType(), e);
} Prevention
- Standardize errorType strings against AWS service error names.
- Log errorType alongside message so production incidents are searchable by type.
- Use $util.appendError when the resolver should continue and still return data.
When it happens
Trigger: A mapping template explicitly calls the two-argument form, e.g. $util.error("mutation failed", "DynamoDB:ConditionalCheckFailedException"). Common in mutation resolvers that translate downstream failures into typed GraphQL errors.
Common situations: Templates copied from AWS docs or blog posts that use typed $util.error for conditional-write failures; clients that switch on errorType and break when the type string doesn't match exactly.
Related errors
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/14ef03b0bc9536c6.
Report an issue: GitHub.