Skip to content
Open
Show file tree
Hide file tree
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
20 changes: 10 additions & 10 deletions capabilities/writetarget/write_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func (c *writeTarget) Execute(ctx context.Context, request capabilities.Capabili
// Validate the config
receiver, err := c.configValidateFn(request)
if err != nil {
msg := builder.buildWriteError(info, 0, "failed to validate config", err.Error())
msg := builder.buildWriteError(info, 0, "failed to validate config: the capability request configuration is invalid. Verify the contract address and request parameters match the expected format", err.Error())
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
}

Expand All @@ -225,15 +225,15 @@ func (c *writeTarget) Execute(ctx context.Context, request capabilities.Capabili
// Source the signed report from the request
signedReport, ok := request.Inputs.Underlying[KeySignedReport]
if !ok {
cause := fmt.Sprintf("input missing required field: '%s'", KeySignedReport)
msg := builder.buildWriteError(info, 0, "failed to source the signed report", cause)
cause := fmt.Sprintf("input missing required field: '%s'. Ensure the upstream capability is providing a signed report in the expected format", KeySignedReport)
msg := builder.buildWriteError(info, 0, "failed to source the signed report: the capability request inputs do not contain the required signed report field", cause)
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
}

// Decode the signed report
inputs := types.SignedReport{}
if err = signedReport.UnwrapTo(&inputs); err != nil {
msg := builder.buildWriteError(info, 0, "failed to parse signed report", err.Error())
msg := builder.buildWriteError(info, 0, "failed to parse signed report: the signed report could not be deserialized. The report format may be incompatible or corrupted", err.Error())
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
}

Expand Down Expand Up @@ -272,18 +272,18 @@ func (c *writeTarget) Execute(ctx context.Context, request capabilities.Capabili

// Validate encoded report is prefixed with workflowID and executionID that match the request meta
if reportDecoded.ExecutionID != request.Metadata.WorkflowExecutionID {
msg := builder.buildWriteError(info, 0, "decoded report execution ID does not match the request", "")
msg := builder.buildWriteError(info, 0, "decoded report execution ID does not match the request: the execution ID embedded in the report does not match the workflow execution ID. This may indicate a report routing error or stale report", "")
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
} else if reportDecoded.WorkflowID != request.Metadata.WorkflowID {
msg := builder.buildWriteError(info, 0, "decoded report workflow ID does not match the request", "")
msg := builder.buildWriteError(info, 0, "decoded report workflow ID does not match the request: the workflow ID embedded in the report does not match the expected workflow ID. This may indicate a report routing error or configuration mismatch", "")
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
}

// Fetch the latest head from the chain (timestamp), retry with a default backoff strategy
ctx = retry.CtxWithID(ctx, info.request.Metadata.WorkflowExecutionID)
head, err := retry.With(ctx, c.lggr, c.cs.LatestHead)
if err != nil {
msg := builder.buildWriteError(info, 0, "failed to fetch the latest head", err.Error())
msg := builder.buildWriteError(info, 0, "failed to fetch the latest head: unable to retrieve the latest block from the chain. The RPC endpoint may be unreachable or the chain may be experiencing issues", err.Error())
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
}

Expand All @@ -301,7 +301,7 @@ func (c *writeTarget) Execute(ctx context.Context, request capabilities.Capabili
state, err := c.targetStrategy.QueryTransmissionState(ctx, info.reportInfo.reportID, request)

if err != nil {
msg := builder.buildWriteError(info, 0, "failed to fetch [TransmissionState]", err.Error())
msg := builder.buildWriteError(info, 0, "failed to fetch transmission state: unable to query the on-chain transmission status via ChainReader. The contract may be unreachable or the report ID may be invalid", err.Error())
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
}

Expand All @@ -311,7 +311,7 @@ func (c *writeTarget) Execute(ctx context.Context, request capabilities.Capabili
case TransmissionStateFailed:
c.lggr.Debugw("Tranmissions previously failed, retrying", "reportID", info.reportInfo.reportID)
case TransmissionStateFatal:
msg := builder.buildWriteError(info, 0, "Transmission attempt fatal", state.Err.Error())
msg := builder.buildWriteError(info, 0, "transmission attempt fatal: a previous transmission attempt encountered an unrecoverable error. This report will not be retried", state.Err.Error())
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
case TransmissionStateSucceeded:
// Source the transmitter address from the on-chain state
Expand All @@ -335,7 +335,7 @@ func (c *writeTarget) Execute(ctx context.Context, request capabilities.Capabili
txID, err := c.targetStrategy.TransmitReport(ctx, inputs.Report, inputs.Context, inputs.Signatures, request)
c.lggr.Debugw("Transaction submitted", "request", request, "transaction-id", txID)
if err != nil {
msg := builder.buildWriteError(info, 0, "failed to transmit the report", err.Error())
msg := builder.buildWriteError(info, 0, "failed to transmit the report: the transaction could not be submitted to the chain via ChainWriter. Check the node's transaction manager logs for details", err.Error())
return capabilities.CapabilityResponse{}, c.asEmittedError(ctx, msg)
}
err = c.beholder.ProtoEmitter.EmitWithLog(ctx, builder.buildWriteSent(info, head, txID))
Expand Down
2 changes: 1 addition & 1 deletion capabilities/writetarget/write_target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func TestWriteTarget_Execute(t *testing.T) {
initialTransmissionState: writetarget.TransmissionState{Status: writetarget.TransmissionStateFatal, Err: errors.New("fatal")},
txState: commontypes.Unknown,
expectError: true,
errorContains: "Transmission attempt fatal",
errorContains: "transmission attempt fatal",
},
{
name: "transmit error",
Expand Down
8 changes: 4 additions & 4 deletions chains/fees/fees.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ func AddPercentage(value *big.Int, percentage uint16) *big.Int {
type feeUnitToChainUnit func(fee *big.Int) string

var (
ErrBumpFeeExceedsLimit = errors.New("fee bump exceeds limit")
ErrBump = errors.New("fee bump failed")
ErrConnectivity = errors.New("transaction propagation issue: transactions are not being mined")
ErrFeeLimitTooLow = errors.New("provided fee limit too low")
ErrBumpFeeExceedsLimit = errors.New("fee bump exceeds limit: the bumped fee would exceed the configured maximum fee cap. Consider increasing the fee limit in your node configuration or wait for network congestion to subside")
ErrBump = errors.New("fee bump failed: unable to increase the transaction fee. The transaction may be stuck. Check node logs for the specific fee estimation error")
ErrConnectivity = errors.New("transaction propagation issue: transactions are not being mined. This may indicate network connectivity problems, a congested network, or gas price set too low. Check your node's connection to the blockchain network")
ErrFeeLimitTooLow = errors.New("provided fee limit too low: the specified gas/fee limit is below the minimum required for this transaction type. Increase the fee limit in your transaction parameters or node configuration")
)

func IsBumpErr(err error) bool {
Expand Down
2 changes: 1 addition & 1 deletion multinode/multi_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/services"
)

var ErrNodeError = fmt.Errorf("no live nodes available")
var ErrNodeError = fmt.Errorf("no live nodes available: all configured RPC nodes are currently unreachable or unhealthy. Check network connectivity and RPC endpoint health. The system will automatically reconnect when nodes become available")

type multiNodeMetrics interface {
RecordNodeStates(ctx context.Context, state string, count int64)
Expand Down
Loading