Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions providers/salesforce/internal/crm/core/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/amp-labs/connectors/common"
"github.com/amp-labs/connectors/common/interpreter"
Expand All @@ -30,6 +31,38 @@ func createError(baseErr error, sfErr jsonError, res *http.Response) error {
return baseErr
}

// fieldNotFoundDocURL points to the troubleshooting guide section for
// Salesforce "No such column" errors raised during reads.
//
//nolint:lll
const fieldNotFoundDocURL = "https://docs.withampersand.com/troubleshooting-guides/salesforce#read-action-no-such-column-error"

// formatFieldNotFoundMessage strips Salesforce-specific noise from a "No such
// column" error message.
func formatFieldNotFoundMessage(msg string) string {
if i := strings.Index(msg, "No such column"); i >= 0 {
msg = msg[i:]
}

msg = strings.TrimSpace(msg)
msg = strings.TrimSuffix(msg,
" Please reference your WSDL or the describe call for the appropriate names.")
msg = strings.TrimSuffix(strings.TrimSpace(msg),
" If you are attempting to use a custom field, be sure to append the '__c' after the custom field name.")

return strings.TrimSpace(msg) + " See " + fieldNotFoundDocURL + " for help troubleshooting this issue."
}

// fieldNotFoundError wraps common.ErrBadRequest for errors.Is matching but
// renders only the supplied message — bypassing the "bad request:" prefix
// and "(HTTP status N)" suffix that createError would otherwise add.
type fieldNotFoundError struct {
msg string
}

func (e *fieldNotFoundError) Error() string { return e.msg }
func (e *fieldNotFoundError) Unwrap() error { return common.ErrBadRequest }

func interpretJSONError(res *http.Response, body []byte) error { // nolint:cyclop
var errs []jsonError
if err := json.Unmarshal(body, &errs); err != nil {
Expand Down Expand Up @@ -59,6 +92,12 @@ func interpretJSONError(res *http.Response, body []byte) error { // nolint:cyclo
case "FIELD_INTEGRITY_EXCEPTION":
fallthrough
case "INVALID_FIELD":
if strings.Contains(sfErr.Message, "No such column") {
return &fieldNotFoundError{
msg: formatFieldNotFoundMessage(sfErr.Message),
}
}

return createError(common.ErrBadRequest, sfErr, res)
case "INVALID_QUERY_LOCATOR":
return createError(common.ErrCursorGone, sfErr, res)
Expand Down
Loading