{"action":"created","issue":{"url":"https://api.github.com/repos/graphql-rust/juniper/issues/40","repository_url":"https://api.github.com/repos/graphql-rust/juniper","labels_url":"https://api.github.com/repos/graphql-rust/juniper/issues/40/labels{/name}","comments_url":"https://api.github.com/repos/graphql-rust/juniper/issues/40/comments","events_url":"https://api.github.com/repos/graphql-rust/juniper/issues/40/events","html_url":"https://github.com/graphql-rust/juniper/issues/40","id":220495319,"number":40,"title":"Complex Errors","user":{"login":"theduke","id":241621,"avatar_url":"https://avatars1.githubusercontent.com/u/241621?v=4","gravatar_id":"","url":"https://api.github.com/users/theduke","html_url":"https://github.com/theduke","followers_url":"https://api.github.com/users/theduke/followers","following_url":"https://api.github.com/users/theduke/following{/other_user}","gists_url":"https://api.github.com/users/theduke/gists{/gist_id}","starred_url":"https://api.github.com/users/theduke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theduke/subscriptions","organizations_url":"https://api.github.com/users/theduke/orgs","repos_url":"https://api.github.com/users/theduke/repos","events_url":"https://api.github.com/users/theduke/events{/privacy}","received_events_url":"https://api.github.com/users/theduke/received_events","type":"User","site_admin":false},"labels":[{"id":440634141,"url":"https://api.github.com/repos/graphql-rust/juniper/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/graphql-rust/juniper/milestones/2","html_url":"https://github.com/graphql-rust/juniper/milestone/2","labels_url":"https://api.github.com/repos/graphql-rust/juniper/milestones/2/labels","id":2686607,"number":2,"title":"0.9","description":"0.9 should be the last stepping stone before a stable 1.0 release.\r\n\r\nThere are a lot of changes to different parts of Juniper, so those should be tested out and validated in a 0.9 release.","creator":{"login":"theduke","id":241621,"avatar_url":"https://avatars1.githubusercontent.com/u/241621?v=4","gravatar_id":"","url":"https://api.github.com/users/theduke","html_url":"https://github.com/theduke","followers_url":"https://api.github.com/users/theduke/followers","following_url":"https://api.github.com/users/theduke/following{/other_user}","gists_url":"https://api.github.com/users/theduke/gists{/gist_id}","starred_url":"https://api.github.com/users/theduke/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/theduke/subscriptions","organizations_url":"https://api.github.com/users/theduke/orgs","repos_url":"https://api.github.com/users/theduke/repos","events_url":"https://api.github.com/users/theduke/events{/privacy}","received_events_url":"https://api.github.com/users/theduke/received_events","type":"User","site_admin":false},"open_issues":7,"closed_issues":0,"state":"open","created_at":"2017-08-07T20:36:47Z","updated_at":"2017-08-07T20:39:27Z","due_on":null,"closed_at":null},"comments":9,"created_at":"2017-04-09T20:08:21Z","updated_at":"2017-08-08T07:12:00Z","closed_at":null,"body":"As I can see, right now, only a simple String error for the `message` field is supported.\r\n\r\nI often need more complex errors with additional data, like this for example:\r\n\r\n```json\r\n\"errors\": [\r\n  {\r\n    \"message\": \"Validation failed\", \r\n    \"code\": \"validation_err\",\r\n    \"data\": {\r\n      \"username\": {\"code\": \"min_length\", \"message\": \"must be at least 5 characters long\", \"meta\": {\"min\": 5, \"max\": 15}}\r\n    }\r\n  }\r\n]\r\n```\r\n\r\nDo you see a way to implement this?\r\n\r\nIt would require changing the type of `FieldResult`.\r\n\r\nAs an idea:\r\n\r\n```rust\r\npub enum FieldError {\r\n  Simple(String),\r\n  Custom(String, json_value::Value),\r\n}\r\n\r\ntype FieldResult<T> = Result<T, FieldError>;\r\n```\r\n\r\nThe problem is the type of the extra data.\r\nIt would require either having FieldError be generic over a type that implements `Serialize` (for serde) or tying it to a value type like [serde_value](https://github.com/arcnmx/serde-value) or `json_value::Value`."},"comment":{"url":"https://api.github.com/repos/graphql-rust/juniper/issues/comments/320870842","html_url":"https://github.com/graphql-rust/juniper/issues/40#issuecomment-320870842","issue_url":"https://api.github.com/repos/graphql-rust/juniper/issues/40","id":320870842,"user":{"login":"mhallin","id":439202,"avatar_url":"https://avatars2.githubusercontent.com/u/439202?v=4","gravatar_id":"","url":"https://api.github.com/users/mhallin","html_url":"https://github.com/mhallin","followers_url":"https://api.github.com/users/mhallin/followers","following_url":"https://api.github.com/users/mhallin/following{/other_user}","gists_url":"https://api.github.com/users/mhallin/gists{/gist_id}","starred_url":"https://api.github.com/users/mhallin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mhallin/subscriptions","organizations_url":"https://api.github.com/users/mhallin/orgs","repos_url":"https://api.github.com/users/mhallin/repos","events_url":"https://api.github.com/users/mhallin/events{/privacy}","received_events_url":"https://api.github.com/users/mhallin/received_events","type":"User","site_admin":false},"created_at":"2017-08-08T07:12:00Z","updated_at":"2017-08-08T07:12:00Z","body":"One possible solution to this and #69 would be to make `FieldError` a struct like:\r\n\r\n```rust\r\nstruct FieldError {\r\n  message: String,\r\n  extra_data: Value,\r\n}\r\n\r\nimpl<E> From<E> for FieldError where E: Display {\r\n  fn from(err: E) -> FieldError {\r\n    FieldError { message: format!(\"{}\", err), extra_data: Value::null() }\r\n  }\r\n}\r\n\r\nimpl FieldError {\r\n  pub fn new<E: Display>(err: E, extra_data: Value) {\r\n    FieldError { message: format!(\"{}\", err), extra_data: extra_data }\r\n  }\r\n```\r\n\r\nThen we could append or include the extra data into the error object when serializing it. Now you could do either the following:\r\n\r\n```rust\r\nlet txn = executor.context().db.transaction()?;\r\n// Would result in { \"message\": \"<internal db error>\", \"locations\": [...] }\r\n\r\n// or\r\nlet txn = executor.context().db.transaction().map_err(\r\n  |e| FieldError::new(e, Value::string(\"Could not start transaction\"))?;\r\n// Would result in { \"message\": \"<internal db error>\", \"locations\": [...], \"data\": \"Could not start transaction\" }\r\n```\r\n\r\n(With reservations for not having checked that the code actually compiles :)"}}
{"actor":{"display_login":"mhallin"}}